1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-marshal-recursive.c Marshalling routines for recursive types
4 * Copyright (C) 2004 Red Hat, Inc.
6 * Licensed under the Academic Free License version 2.1
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.
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.
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
24 #include "dbus-marshal-recursive.h"
25 #include "dbus-internals.h"
28 * @addtogroup DBusMarshal
33 first_type_in_signature (const DBusString *str,
38 t = _dbus_string_get_byte (str, pos);
40 if (t == DBUS_STRUCT_BEGIN_CHAR)
41 return DBUS_TYPE_STRUCT;
47 element_type_get_alignment (const DBusString *str,
50 return _dbus_type_get_alignment (first_type_in_signature (str, pos));
54 _dbus_type_reader_init (DBusTypeReader *reader,
56 const DBusString *type_str,
58 const DBusString *value_str,
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;
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));
74 _dbus_type_reader_get_current_type (DBusTypeReader *reader)
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
82 if (reader->container_type == DBUS_TYPE_INVALID)
84 t = first_type_in_signature (reader->type_str,
87 else if (reader->container_type == DBUS_TYPE_STRUCT)
89 if (reader->u.strct.finished)
90 t = DBUS_TYPE_INVALID;
92 t = first_type_in_signature (reader->type_str,
95 else if (reader->container_type == DBUS_TYPE_ARRAY)
97 /* return the array element type if elements remain, and
98 * TYPE_INVALID otherwise
102 end_pos = reader->u.array.start_pos + reader->u.array.len;
104 _dbus_assert (reader->value_pos <= end_pos);
105 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
107 if (reader->value_pos < end_pos)
108 t = reader->u.array.element_type;
110 t = DBUS_TYPE_INVALID;
114 _dbus_assert_not_reached ("reader->container_type should not be set to this");
115 t = DBUS_TYPE_INVALID; /* quiet gcc */
118 _dbus_assert (t != DBUS_STRUCT_END_CHAR);
119 _dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR);
122 _dbus_verbose (" type reader %p current type_pos = %d type = %s\n",
123 reader, reader->type_pos,
124 _dbus_type_to_string (t));
131 _dbus_type_reader_array_is_empty (DBusTypeReader *reader)
133 dbus_uint32_t array_len;
136 _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY,
139 len_pos = _DBUS_ALIGN_VALUE (reader->value_pos, 4);
141 _dbus_demarshal_basic_type (reader->value_str,
147 return array_len == 0;
151 _dbus_type_reader_read_basic (DBusTypeReader *reader,
154 if (reader->container_type == DBUS_TYPE_INVALID ||
155 reader->container_type == DBUS_TYPE_STRUCT ||
156 reader->container_type == DBUS_TYPE_ARRAY)
161 t = _dbus_type_reader_get_current_type (reader);
163 next = reader->value_pos;
164 _dbus_demarshal_basic_type (reader->value_str,
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));
176 _dbus_assert_not_reached ("reader->container_type should not be set to this");
181 _dbus_type_reader_read_array_of_basic (DBusTypeReader *reader,
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.
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.
199 * @param reader the reader
200 * @param sub a reader to init pointing to the first child
203 _dbus_type_reader_recurse (DBusTypeReader *reader,
208 t = first_type_in_signature (reader->type_str, reader->type_pos);
210 /* point subreader at the same place as reader */
211 _dbus_type_reader_init (sub,
218 if (t == DBUS_TYPE_STRUCT)
220 sub->container_type = DBUS_TYPE_STRUCT;
224 /* struct has 8 byte alignment */
225 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
227 sub->u.strct.finished = FALSE;
229 else if (t == DBUS_TYPE_ARRAY)
231 dbus_uint32_t array_len;
234 _dbus_return_if_fail (!_dbus_type_reader_array_is_empty (reader));
236 sub->container_type = DBUS_TYPE_ARRAY;
238 /* point type_pos at the array element type */
241 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
243 _dbus_demarshal_basic_type (sub->value_str,
249 sub->u.array.len = array_len;
251 alignment = element_type_get_alignment (sub->type_str,
254 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
256 sub->u.array.element_type = first_type_in_signature (sub->type_str,
258 sub->u.array.start_pos = sub->value_pos;
260 _dbus_verbose (" type reader %p array start = %d array len = %d array element type = %s\n",
262 sub->u.array.start_pos,
264 _dbus_type_to_string (sub->u.array.element_type));
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 */
274 _dbus_assert_not_reached ("don't yet handle recursing into this type");
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));
283 skip_one_complete_type (const DBusString *type_str,
286 while (_dbus_string_get_byte (type_str, *type_pos) == DBUS_TYPE_ARRAY)
289 if (_dbus_string_get_byte (type_str, *type_pos) == DBUS_STRUCT_BEGIN_CHAR)
296 switch (_dbus_string_get_byte (type_str, *type_pos))
298 case DBUS_STRUCT_BEGIN_CHAR:
301 case DBUS_STRUCT_END_CHAR:
304 case DBUS_TYPE_INVALID:
305 _dbus_assert_not_reached ("unbalanced parens in signature");
316 skip_array_values (int element_type,
317 const DBusString *value_str,
321 dbus_uint32_t array_len;
325 pos = _DBUS_ALIGN_VALUE (*value_pos, 4);
327 _dbus_demarshal_basic_type (value_str,
333 alignment = _dbus_type_get_alignment (element_type);
335 pos = _DBUS_ALIGN_VALUE (pos, alignment);
337 *value_pos = pos + array_len;
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.
345 * @param reader the reader
346 * @returns FALSE if nothing more to read at or below this level
349 _dbus_type_reader_next (DBusTypeReader *reader)
353 t = _dbus_type_reader_get_current_type (reader);
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));
360 if (t == DBUS_TYPE_INVALID)
363 if (reader->container_type == DBUS_TYPE_INVALID ||
364 reader->container_type == DBUS_TYPE_STRUCT)
368 case DBUS_TYPE_STRUCT:
369 /* Scan forward over the entire container contents */
373 /* Recurse into the struct */
374 _dbus_type_reader_recurse (reader, &sub);
376 /* Skip everything in this subreader */
377 while (_dbus_type_reader_next (&sub))
382 /* Now we are at the end of this container */
383 reader->type_pos = sub.type_pos;
384 reader->value_pos = sub.value_pos;
388 case DBUS_TYPE_ARRAY:
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);
398 _dbus_marshal_skip_basic_type (reader->value_str,
399 t, reader->byte_order,
401 reader->type_pos += 1;
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())
410 if (reader->container_type == DBUS_TYPE_STRUCT)
412 t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
413 if (t == DBUS_STRUCT_END_CHAR)
415 reader->type_pos += 1;
416 reader->u.strct.finished = TRUE;
420 else if (reader->container_type == DBUS_TYPE_ARRAY)
422 /* Skip one array element */
425 end_pos = reader->u.array.start_pos + reader->u.array.len;
427 _dbus_assert (reader->value_pos < end_pos);
428 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
430 if (reader->u.array.element_type == DBUS_TYPE_STRUCT)
434 /* Recurse into the struct */
435 _dbus_type_reader_recurse (reader, &sub);
437 /* Skip everything in this element */
438 while (_dbus_type_reader_next (&sub))
443 /* Now we are at the end of this element */
444 reader->value_pos = sub.value_pos;
446 else if (reader->u.array.element_type == DBUS_TYPE_ARRAY)
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);
454 _dbus_marshal_skip_basic_type (reader->value_str,
455 t, reader->byte_order,
459 _dbus_assert (reader->value_pos <= end_pos);
461 if (reader->value_pos == end_pos)
463 skip_one_complete_type (reader->type_str,
469 _dbus_assert_not_reached ("reader->container_type should not be set to this");
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)));
477 return _dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID;
481 _dbus_type_writer_init (DBusTypeWriter *writer,
483 DBusString *type_str,
485 DBusString *value_str,
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;
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));
501 _dbus_type_writer_write_basic_no_typecode (DBusTypeWriter *writer,
508 old_value_len = _dbus_string_get_length (writer->value_str);
510 if (!_dbus_marshal_basic_type (writer->value_str,
517 bytes_written = _dbus_string_get_length (writer->value_str) - old_value_len;
519 writer->value_pos += bytes_written;
524 /* If our parent is an array, things are a little bit complicated.
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.
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
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.
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.
542 * While inside an array type_pos points to the expected next
543 * typecode, rather than the next place we could write a typecode.
546 writer_recurse_init_and_check (DBusTypeWriter *writer,
550 _dbus_type_writer_init (sub,
557 sub->container_type = container_type;
559 if (writer->inside_array || sub->container_type == DBUS_TYPE_ARRAY)
560 sub->inside_array = TRUE;
562 sub->inside_array = FALSE;
564 #ifndef DBUS_DISABLE_CHECKS
565 if (writer->inside_array)
569 expected = first_type_in_signature (writer->type_str, writer->type_pos);
571 if (expected != sub->container_type)
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");
579 #endif /* DBUS_DISABLE_CHECKS */
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,
588 _dbus_type_to_string (sub->container_type));
592 write_or_verify_typecode (DBusTypeWriter *writer,
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.
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));
603 if (writer->inside_array)
605 #ifndef DBUS_DISABLE_CHECKS
609 expected = _dbus_string_get_byte (writer->type_str, writer->type_pos);
611 if (expected != typecode)
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");
618 #endif /* DBUS_DISABLE_CHECKS */
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.
624 if (writer->container_type != DBUS_TYPE_ARRAY)
625 writer->type_pos += 1;
629 if (!_dbus_string_insert_byte (writer->type_str,
634 writer->type_pos += 1;
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));
645 _dbus_type_writer_recurse (DBusTypeWriter *writer,
649 writer_recurse_init_and_check (writer, container_type, sub);
651 switch (container_type)
653 case DBUS_TYPE_STRUCT:
655 /* Ensure that we'll be able to add alignment padding and the typecode */
656 if (!_dbus_string_alloc_space (sub->value_str, 8))
659 if (!write_or_verify_typecode (sub, DBUS_STRUCT_BEGIN_CHAR))
660 _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
662 if (!_dbus_string_insert_bytes (sub->value_str,
664 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
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);
670 case DBUS_TYPE_ARRAY:
671 _dbus_assert_not_reached ("use recurse_array() for arrays");
674 _dbus_assert_not_reached ("container_type unhandled");
682 _dbus_type_writer_recurse_array (DBusTypeWriter *writer,
683 const char *element_type,
686 int element_type_len;
687 DBusString element_type_str;
688 dbus_uint32_t value = 0;
693 writer_recurse_init_and_check (writer, DBUS_TYPE_ARRAY, sub);
695 #ifndef DBUS_DISABLE_CHECKS
696 if (writer->container_type == DBUS_TYPE_ARRAY)
698 DBusString parent_elements;
700 _dbus_assert (element_type != NULL);
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,
707 if (!_dbus_string_starts_with_c_str (&parent_elements, element_type))
709 _dbus_warn ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
711 _dbus_assert_not_reached ("incompatible type for child array");
714 #endif /* DBUS_DISABLE_CHECKS */
716 _dbus_string_init_const (&element_type_str, element_type);
717 element_type_len = _dbus_string_get_length (&element_type_str);
719 /* 4 bytes for the array length and 4 bytes possible padding */
720 if (!_dbus_string_alloc_space (sub->value_str, 8))
723 sub->type_pos += 1; /* move to point to the element type, since type_pos
724 * should be the expected type for further writes
726 sub->u.array.element_type_pos = sub->type_pos;
727 sub->u.array.element_type_len = element_type_len;
729 if (!writer->inside_array)
731 /* sub is a toplevel/outermost array so we need to write the type data */
733 /* alloc space for array typecode, element signature, possible 7
736 if (!_dbus_string_alloc_space (writer->type_str, 1 + element_type_len + 7))
739 if (!_dbus_string_insert_byte (writer->type_str,
742 _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
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");
749 /* Write the length */
750 sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
752 if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
754 _dbus_assert_not_reached ("should not have failed to insert array len");
756 _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
758 /* Write alignment padding for array elements */
759 _dbus_string_init_const (&str, element_type);
760 alignment = element_type_get_alignment (&str, 0);
762 aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
763 if (aligned != sub->value_pos)
765 if (!_dbus_string_insert_bytes (sub->value_str,
767 aligned - sub->value_pos,
769 _dbus_assert_not_reached ("should not have failed to insert alignment padding");
771 sub->value_pos = aligned;
773 sub->u.array.start_pos = sub->value_pos;
775 _dbus_assert (sub->u.array.start_pos == sub->value_pos);
776 _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
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));
785 _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
788 _dbus_assert (sub->type_pos > 0); /* can't be recursed if this fails */
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,
796 _dbus_type_to_string (sub->container_type));
798 if (sub->container_type == DBUS_TYPE_STRUCT)
800 if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
803 else if (sub->container_type == DBUS_TYPE_ARRAY)
807 /* Set the array length */
808 len = sub->value_pos - sub->u.array.start_pos;
809 _dbus_marshal_set_uint32 (sub->value_str,
811 sub->u.array.len_pos,
813 _dbus_verbose (" filled in sub array len to %u at len_pos %d\n",
814 len, sub->u.array.len_pos);
817 /* Now get type_pos right for the parent writer. Here are the cases:
819 * Cases !writer->inside_array:
820 * (in these cases we want to update to the new insertion point)
822 * - we recursed from STRUCT or INVALID into STRUCT and type_pos
823 * is the new insertion point in all cases
824 * writer->type_pos = sub->type_pos
826 * - we recursed from STRUCT or INVALID into ARRAY, so type_pos in
827 * the child is the array element type, and type_pos in the parent
828 * currently is the child array type but should be set to the
829 * insertion point just after the element type
830 * writer->type_pos = sub->element_type_pos + sub->element_type_len
832 * Cases where writer->inside_array:
833 * (in these cases we want to update to next expected write)
835 * - we recursed from STRUCT into STRUCT somewhere inside an array
836 * element; type_pos in parent is at the child's begin_struct, and
837 * type_pos in the child is at the next field type for the parent
838 * writer->type_pos = sub->type_pos
840 * - we recursed from STRUCT or INVALID into ARRAY somewhere inside
841 * an array element, so type_pos in the parent is at the child's
842 * array typecode, and type_pos in the child is at the array
844 * writer->type_pos = sub->element_type_pos + sub->element_type_len
846 * - we recursed from ARRAY into STRUCT, so type_pos in the
847 * parent is the element type starting with STRUCT,
848 * and type_pos in the child is just after the end_struct code
849 * writer->type_pos should remain as-is
851 * - we recursed from ARRAY into ARRAY, so type_pos in the
852 * parent is the element type starting with child's ARRAY code,
853 * type_pos in the child is the element type of the
855 * writer->type_pos should remain as-is
857 if (writer->container_type == DBUS_TYPE_ARRAY)
859 /* Don't do anything, because sub was an element, and the type
860 * of subsequent elements should be the same
863 else if (sub->container_type == DBUS_TYPE_ARRAY)
865 /* Jump to the next type in the parent's type signature,
866 * which is after our array element type
868 _dbus_assert (writer->container_type != DBUS_TYPE_ARRAY);
869 writer->type_pos = sub->u.array.element_type_pos + sub->u.array.element_type_len;
873 writer->type_pos = sub->type_pos;
876 writer->value_pos = sub->value_pos;
878 _dbus_verbose (" type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
879 writer, writer->type_pos, writer->value_pos,
880 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
886 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
892 /* First ensure that our type realloc will succeed */
893 if (!_dbus_string_alloc_space (writer->type_str, 1))
898 if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
901 if (!write_or_verify_typecode (writer, type))
902 _dbus_assert_not_reached ("failed to write typecode after prealloc");
907 _dbus_verbose (" type writer %p basic type_pos = %d value_pos = %d inside_array = %d\n",
908 writer, writer->type_pos, writer->value_pos, writer->inside_array);
914 _dbus_type_writer_write_array (DBusTypeWriter *writer,
923 /** @} */ /* end of DBusMarshal group */
925 #ifdef DBUS_BUILD_TESTS
926 #include "dbus-test.h"
932 DBusString signature;
943 data_block_init (DataBlock *block)
945 if (!_dbus_string_init (&block->signature))
948 if (!_dbus_string_init (&block->body))
950 _dbus_string_free (&block->signature);
958 data_block_free (DataBlock *block)
960 _dbus_string_free (&block->signature);
961 _dbus_string_free (&block->body);
965 data_block_save (DataBlock *block,
966 DataBlockState *state)
968 state->saved_sig_len = _dbus_string_get_length (&block->signature);
969 state->saved_body_len = _dbus_string_get_length (&block->body);
973 data_block_restore (DataBlock *block,
974 DataBlockState *state)
976 /* These set_length should be shortening things so should always work */
978 if (!_dbus_string_set_length (&block->signature,
979 state->saved_sig_len))
980 _dbus_assert_not_reached ("could not restore signature length");
982 if (!_dbus_string_set_length (&block->body,
983 state->saved_body_len))
984 _dbus_assert_not_reached ("could not restore body length");
988 data_block_init_reader_writer (DataBlock *block,
990 DBusTypeReader *reader,
991 DBusTypeWriter *writer)
993 _dbus_type_reader_init (reader,
996 _dbus_string_get_length (&block->signature),
998 _dbus_string_get_length (&block->body));
1000 _dbus_type_writer_init (writer,
1003 _dbus_string_get_length (&block->signature),
1005 _dbus_string_get_length (&block->body));
1008 #define NEXT_EXPECTING_TRUE(reader) do { if (!_dbus_type_reader_next (reader)) \
1010 _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d\n", \
1011 _DBUS_FUNCTION_NAME, __LINE__); \
1012 _dbus_assert_not_reached ("test failed"); \
1016 #define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader)) \
1018 _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d\n", \
1019 _DBUS_FUNCTION_NAME, __LINE__); \
1020 _dbus_assert_not_reached ("test failed"); \
1022 check_expected_type (reader, DBUS_TYPE_INVALID); \
1025 #define SAMPLE_INT32 12345678
1026 #define SAMPLE_INT32_ALTERNATE 53781429
1028 write_int32 (DataBlock *block,
1029 DBusTypeWriter *writer)
1031 dbus_int32_t v = SAMPLE_INT32;
1033 return _dbus_type_writer_write_basic (writer,
1039 real_check_expected_type (DBusTypeReader *reader,
1041 const char *funcname,
1046 t = _dbus_type_reader_get_current_type (reader);
1050 _dbus_warn ("Read type %s while expecting %s at %s line %d\n",
1051 _dbus_type_to_string (t),
1052 _dbus_type_to_string (expected),
1059 #define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__)
1062 read_int32 (DataBlock *block,
1063 DBusTypeReader *reader)
1067 check_expected_type (reader, DBUS_TYPE_INT32);
1069 _dbus_type_reader_read_basic (reader,
1070 (dbus_int32_t*) &v);
1072 _dbus_assert (v == SAMPLE_INT32);
1078 write_struct_of_int32 (DataBlock *block,
1079 DBusTypeWriter *writer)
1082 DataBlockState saved;
1085 data_block_save (block, &saved);
1087 if (!_dbus_type_writer_recurse (writer,
1093 if (!_dbus_type_writer_write_basic (&sub,
1097 data_block_restore (block, &saved);
1101 v = SAMPLE_INT32_ALTERNATE;
1102 if (!_dbus_type_writer_write_basic (&sub,
1106 data_block_restore (block, &saved);
1110 if (!_dbus_type_writer_unrecurse (writer, &sub))
1112 data_block_restore (block, &saved);
1120 read_struct_of_int32 (DataBlock *block,
1121 DBusTypeReader *reader)
1126 check_expected_type (reader, DBUS_TYPE_STRUCT);
1128 _dbus_type_reader_recurse (reader, &sub);
1130 check_expected_type (&sub, DBUS_TYPE_INT32);
1132 _dbus_type_reader_read_basic (&sub,
1133 (dbus_int32_t*) &v);
1135 _dbus_assert (v == SAMPLE_INT32);
1137 NEXT_EXPECTING_TRUE (&sub);
1138 check_expected_type (&sub, DBUS_TYPE_INT32);
1140 _dbus_type_reader_read_basic (&sub,
1141 (dbus_int32_t*) &v);
1143 _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1145 NEXT_EXPECTING_FALSE (&sub);
1151 write_struct_of_structs (DataBlock *block,
1152 DBusTypeWriter *writer)
1154 DataBlockState saved;
1157 data_block_save (block, &saved);
1159 if (!_dbus_type_writer_recurse (writer,
1164 if (!write_struct_of_int32 (block, &sub))
1166 data_block_restore (block, &saved);
1169 if (!write_struct_of_int32 (block, &sub))
1171 data_block_restore (block, &saved);
1174 if (!write_struct_of_int32 (block, &sub))
1176 data_block_restore (block, &saved);
1180 if (!_dbus_type_writer_unrecurse (writer, &sub))
1182 data_block_restore (block, &saved);
1190 read_struct_of_structs (DataBlock *block,
1191 DBusTypeReader *reader)
1195 check_expected_type (reader, DBUS_TYPE_STRUCT);
1197 _dbus_type_reader_recurse (reader, &sub);
1199 if (!read_struct_of_int32 (block, &sub))
1202 NEXT_EXPECTING_TRUE (&sub);
1203 if (!read_struct_of_int32 (block, &sub))
1206 NEXT_EXPECTING_TRUE (&sub);
1207 if (!read_struct_of_int32 (block, &sub))
1210 NEXT_EXPECTING_FALSE (&sub);
1216 write_struct_of_structs_of_structs (DataBlock *block,
1217 DBusTypeWriter *writer)
1219 DataBlockState saved;
1222 data_block_save (block, &saved);
1224 if (!_dbus_type_writer_recurse (writer,
1229 if (!write_struct_of_structs (block, &sub))
1231 data_block_restore (block, &saved);
1234 if (!write_struct_of_structs (block, &sub))
1236 data_block_restore (block, &saved);
1240 if (!_dbus_type_writer_unrecurse (writer, &sub))
1242 data_block_restore (block, &saved);
1250 read_struct_of_structs_of_structs (DataBlock *block,
1251 DBusTypeReader *reader)
1255 check_expected_type (reader, DBUS_TYPE_STRUCT);
1257 _dbus_type_reader_recurse (reader, &sub);
1259 if (!read_struct_of_structs (block, &sub))
1262 NEXT_EXPECTING_TRUE (&sub);
1263 if (!read_struct_of_structs (block, &sub))
1266 NEXT_EXPECTING_FALSE (&sub);
1272 write_array_of_int32 (DataBlock *block,
1273 DBusTypeWriter *writer)
1276 DataBlockState saved;
1279 data_block_save (block, &saved);
1281 if (!_dbus_type_writer_recurse_array (writer,
1282 DBUS_TYPE_INT32_AS_STRING,
1286 v = SAMPLE_INT32_ALTERNATE;
1287 if (!_dbus_type_writer_write_basic (&sub,
1291 data_block_restore (block, &saved);
1296 if (!_dbus_type_writer_write_basic (&sub,
1300 data_block_restore (block, &saved);
1305 if (!_dbus_type_writer_write_basic (&sub,
1309 data_block_restore (block, &saved);
1313 if (!_dbus_type_writer_unrecurse (writer, &sub))
1315 data_block_restore (block, &saved);
1323 read_array_of_int32 (DataBlock *block,
1324 DBusTypeReader *reader)
1329 check_expected_type (reader, DBUS_TYPE_ARRAY);
1331 _dbus_type_reader_recurse (reader, &sub);
1333 check_expected_type (&sub, DBUS_TYPE_INT32);
1335 _dbus_type_reader_read_basic (&sub,
1336 (dbus_int32_t*) &v);
1338 _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1340 NEXT_EXPECTING_TRUE (&sub);
1341 check_expected_type (&sub, DBUS_TYPE_INT32);
1343 _dbus_type_reader_read_basic (&sub,
1344 (dbus_int32_t*) &v);
1346 _dbus_assert (v == SAMPLE_INT32);
1348 NEXT_EXPECTING_TRUE (&sub);
1349 check_expected_type (&sub, DBUS_TYPE_INT32);
1351 _dbus_type_reader_read_basic (&sub,
1352 (dbus_int32_t*) &v);
1354 _dbus_assert (v == SAMPLE_INT32);
1356 NEXT_EXPECTING_FALSE (&sub);
1363 write_array_of_int32_empty (DataBlock *block,
1364 DBusTypeWriter *writer)
1366 DataBlockState saved;
1369 data_block_save (block, &saved);
1371 if (!_dbus_type_writer_recurse_array (writer,
1372 DBUS_TYPE_INT32_AS_STRING,
1376 if (!_dbus_type_writer_unrecurse (writer, &sub))
1378 data_block_restore (block, &saved);
1386 read_array_of_int32_empty (DataBlock *block,
1387 DBusTypeReader *reader)
1389 check_expected_type (reader, DBUS_TYPE_ARRAY);
1391 /* We are iterating over values not types. Thus we can't recurse
1394 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1400 write_array_of_array_of_int32 (DataBlock *block,
1401 DBusTypeWriter *writer)
1403 DataBlockState saved;
1406 data_block_save (block, &saved);
1408 if (!_dbus_type_writer_recurse_array (writer,
1409 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1413 if (!write_array_of_int32 (block, &sub))
1415 data_block_restore (block, &saved);
1419 if (!write_array_of_int32 (block, &sub))
1421 data_block_restore (block, &saved);
1425 if (!write_array_of_int32_empty (block, &sub))
1427 data_block_restore (block, &saved);
1431 if (!write_array_of_int32 (block, &sub))
1433 data_block_restore (block, &saved);
1437 if (!_dbus_type_writer_unrecurse (writer, &sub))
1439 data_block_restore (block, &saved);
1447 read_array_of_array_of_int32 (DataBlock *block,
1448 DBusTypeReader *reader)
1452 check_expected_type (reader, DBUS_TYPE_ARRAY);
1454 _dbus_type_reader_recurse (reader, &sub);
1456 if (!read_array_of_int32 (block, &sub))
1459 NEXT_EXPECTING_TRUE (&sub);
1460 if (!read_array_of_int32 (block, &sub))
1463 NEXT_EXPECTING_TRUE (&sub);
1464 if (!read_array_of_int32_empty (block, &sub))
1467 NEXT_EXPECTING_TRUE (&sub);
1468 if (!read_array_of_int32 (block, &sub))
1471 NEXT_EXPECTING_FALSE (&sub);
1478 write_array_of_array_of_int32_empty (DataBlock *block,
1479 DBusTypeWriter *writer)
1481 DataBlockState saved;
1484 data_block_save (block, &saved);
1486 if (!_dbus_type_writer_recurse_array (writer,
1487 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1491 if (!_dbus_type_writer_unrecurse (writer, &sub))
1493 data_block_restore (block, &saved);
1501 read_array_of_array_of_int32_empty (DataBlock *block,
1502 DBusTypeReader *reader)
1504 check_expected_type (reader, DBUS_TYPE_ARRAY);
1506 /* We are iterating over values, not types. Thus
1507 * we can't recurse in here.
1510 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1516 write_array_of_array_of_array_of_int32 (DataBlock *block,
1517 DBusTypeWriter *writer)
1519 DataBlockState saved;
1522 data_block_save (block, &saved);
1524 if (!_dbus_type_writer_recurse_array (writer,
1525 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1529 if (!write_array_of_array_of_int32 (block, &sub))
1531 data_block_restore (block, &saved);
1535 if (!write_array_of_array_of_int32 (block, &sub))
1537 data_block_restore (block, &saved);
1541 if (!write_array_of_array_of_int32_empty (block, &sub))
1543 data_block_restore (block, &saved);
1547 if (!_dbus_type_writer_unrecurse (writer, &sub))
1549 data_block_restore (block, &saved);
1557 read_array_of_array_of_array_of_int32 (DataBlock *block,
1558 DBusTypeReader *reader)
1562 check_expected_type (reader, DBUS_TYPE_ARRAY);
1564 _dbus_type_reader_recurse (reader, &sub);
1566 if (!read_array_of_array_of_int32 (block, &sub))
1569 NEXT_EXPECTING_TRUE (&sub);
1570 if (!read_array_of_array_of_int32 (block, &sub))
1573 NEXT_EXPECTING_TRUE (&sub);
1574 if (!read_array_of_array_of_int32_empty (block, &sub))
1577 NEXT_EXPECTING_FALSE (&sub);
1583 write_struct_of_array_of_int32 (DataBlock *block,
1584 DBusTypeWriter *writer)
1586 DataBlockState saved;
1589 data_block_save (block, &saved);
1591 if (!_dbus_type_writer_recurse (writer,
1596 if (!write_array_of_int32 (block, &sub))
1598 data_block_restore (block, &saved);
1602 if (!write_array_of_int32_empty (block, &sub))
1604 data_block_restore (block, &saved);
1608 if (!_dbus_type_writer_unrecurse (writer, &sub))
1610 data_block_restore (block, &saved);
1618 read_struct_of_array_of_int32 (DataBlock *block,
1619 DBusTypeReader *reader)
1623 check_expected_type (reader, DBUS_TYPE_STRUCT);
1625 _dbus_type_reader_recurse (reader, &sub);
1627 check_expected_type (&sub, DBUS_TYPE_ARRAY);
1629 if (!read_array_of_int32 (block, &sub))
1632 NEXT_EXPECTING_TRUE (&sub);
1633 if (!read_array_of_int32_empty (block, &sub))
1636 NEXT_EXPECTING_FALSE (&sub);
1642 write_struct_of_struct_of_array_of_int32 (DataBlock *block,
1643 DBusTypeWriter *writer)
1645 DataBlockState saved;
1648 data_block_save (block, &saved);
1650 if (!_dbus_type_writer_recurse (writer,
1655 if (!write_struct_of_array_of_int32 (block, &sub))
1657 data_block_restore (block, &saved);
1660 if (!write_struct_of_array_of_int32 (block, &sub))
1662 data_block_restore (block, &saved);
1665 if (!write_struct_of_array_of_int32 (block, &sub))
1667 data_block_restore (block, &saved);
1671 if (!_dbus_type_writer_unrecurse (writer, &sub))
1673 data_block_restore (block, &saved);
1681 read_struct_of_struct_of_array_of_int32 (DataBlock *block,
1682 DBusTypeReader *reader)
1686 check_expected_type (reader, DBUS_TYPE_STRUCT);
1688 _dbus_type_reader_recurse (reader, &sub);
1690 if (!read_struct_of_array_of_int32 (block, &sub))
1693 NEXT_EXPECTING_TRUE (&sub);
1694 if (!read_struct_of_array_of_int32 (block, &sub))
1697 NEXT_EXPECTING_TRUE (&sub);
1698 if (!read_struct_of_array_of_int32 (block, &sub))
1701 NEXT_EXPECTING_FALSE (&sub);
1707 write_array_of_struct_of_int32 (DataBlock *block,
1708 DBusTypeWriter *writer)
1710 DataBlockState saved;
1713 data_block_save (block, &saved);
1715 if (!_dbus_type_writer_recurse_array (writer,
1716 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
1717 DBUS_TYPE_INT32_AS_STRING
1718 DBUS_TYPE_INT32_AS_STRING
1719 DBUS_STRUCT_END_CHAR_AS_STRING,
1723 if (!write_struct_of_int32 (block, &sub))
1725 data_block_restore (block, &saved);
1729 if (!write_struct_of_int32 (block, &sub))
1731 data_block_restore (block, &saved);
1735 if (!write_struct_of_int32 (block, &sub))
1737 data_block_restore (block, &saved);
1741 if (!_dbus_type_writer_unrecurse (writer, &sub))
1743 data_block_restore (block, &saved);
1751 read_array_of_struct_of_int32 (DataBlock *block,
1752 DBusTypeReader *reader)
1756 check_expected_type (reader, DBUS_TYPE_ARRAY);
1758 _dbus_type_reader_recurse (reader, &sub);
1760 check_expected_type (&sub, DBUS_TYPE_STRUCT);
1762 if (!read_struct_of_int32 (block, &sub))
1765 NEXT_EXPECTING_TRUE (&sub);
1767 if (!read_struct_of_int32 (block, &sub))
1770 NEXT_EXPECTING_TRUE (&sub);
1772 if (!read_struct_of_int32 (block, &sub))
1775 NEXT_EXPECTING_FALSE (&sub);
1782 write_array_of_array_of_struct_of_int32 (DataBlock *block,
1783 DBusTypeWriter *writer)
1785 DataBlockState saved;
1788 data_block_save (block, &saved);
1790 if (!_dbus_type_writer_recurse_array (writer,
1791 DBUS_TYPE_ARRAY_AS_STRING
1792 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
1793 DBUS_TYPE_INT32_AS_STRING
1794 DBUS_TYPE_INT32_AS_STRING
1795 DBUS_STRUCT_END_CHAR_AS_STRING,
1799 if (!write_array_of_struct_of_int32 (block, &sub))
1801 data_block_restore (block, &saved);
1805 if (!write_array_of_struct_of_int32 (block, &sub))
1807 data_block_restore (block, &saved);
1811 if (!write_array_of_struct_of_int32 (block, &sub))
1813 data_block_restore (block, &saved);
1817 if (!_dbus_type_writer_unrecurse (writer, &sub))
1819 data_block_restore (block, &saved);
1827 read_array_of_array_of_struct_of_int32 (DataBlock *block,
1828 DBusTypeReader *reader)
1832 check_expected_type (reader, DBUS_TYPE_ARRAY);
1834 _dbus_type_reader_recurse (reader, &sub);
1836 check_expected_type (&sub, DBUS_TYPE_ARRAY);
1838 if (!read_array_of_struct_of_int32 (block, &sub))
1841 NEXT_EXPECTING_TRUE (&sub);
1843 if (!read_array_of_struct_of_int32 (block, &sub))
1846 NEXT_EXPECTING_TRUE (&sub);
1848 if (!read_array_of_struct_of_int32 (block, &sub))
1851 NEXT_EXPECTING_FALSE (&sub);
1857 write_struct_of_array_of_struct_of_int32 (DataBlock *block,
1858 DBusTypeWriter *writer)
1860 DataBlockState saved;
1863 data_block_save (block, &saved);
1865 if (!_dbus_type_writer_recurse (writer,
1870 if (!write_array_of_struct_of_int32 (block, &sub))
1872 data_block_restore (block, &saved);
1875 if (!write_array_of_struct_of_int32 (block, &sub))
1877 data_block_restore (block, &saved);
1880 if (!write_array_of_struct_of_int32 (block, &sub))
1882 data_block_restore (block, &saved);
1886 if (!_dbus_type_writer_unrecurse (writer, &sub))
1888 data_block_restore (block, &saved);
1896 read_struct_of_array_of_struct_of_int32 (DataBlock *block,
1897 DBusTypeReader *reader)
1901 check_expected_type (reader, DBUS_TYPE_STRUCT);
1903 _dbus_type_reader_recurse (reader, &sub);
1905 if (!read_array_of_struct_of_int32 (block, &sub))
1908 NEXT_EXPECTING_TRUE (&sub);
1909 if (!read_array_of_struct_of_int32 (block, &sub))
1912 NEXT_EXPECTING_TRUE (&sub);
1913 if (!read_array_of_struct_of_int32 (block, &sub))
1916 NEXT_EXPECTING_FALSE (&sub);
1922 write_array_of_struct_of_array_of_int32 (DataBlock *block,
1923 DBusTypeWriter *writer)
1925 DataBlockState saved;
1928 data_block_save (block, &saved);
1930 if (!_dbus_type_writer_recurse_array (writer,
1931 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
1932 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
1933 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
1934 DBUS_STRUCT_END_CHAR_AS_STRING,
1938 if (!write_struct_of_array_of_int32 (block, &sub))
1940 data_block_restore (block, &saved);
1944 if (!write_struct_of_array_of_int32 (block, &sub))
1946 data_block_restore (block, &saved);
1950 if (!write_struct_of_array_of_int32 (block, &sub))
1952 data_block_restore (block, &saved);
1956 if (!_dbus_type_writer_unrecurse (writer, &sub))
1958 data_block_restore (block, &saved);
1966 read_array_of_struct_of_array_of_int32 (DataBlock *block,
1967 DBusTypeReader *reader)
1971 check_expected_type (reader, DBUS_TYPE_ARRAY);
1973 _dbus_type_reader_recurse (reader, &sub);
1975 check_expected_type (&sub, DBUS_TYPE_STRUCT);
1977 if (!read_struct_of_array_of_int32 (block, &sub))
1980 NEXT_EXPECTING_TRUE (&sub);
1982 if (!read_struct_of_array_of_int32 (block, &sub))
1985 NEXT_EXPECTING_TRUE (&sub);
1987 if (!read_struct_of_array_of_int32 (block, &sub))
1990 NEXT_EXPECTING_FALSE (&sub);
2000 ITEM_STRUCT_OF_INT32,
2001 ITEM_STRUCT_OF_STRUCTS,
2002 ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2004 ITEM_ARRAY_OF_INT32,
2005 ITEM_ARRAY_OF_INT32_EMPTY,
2006 ITEM_ARRAY_OF_ARRAY_OF_INT32,
2007 ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2008 ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2010 ITEM_STRUCT_OF_ARRAY_OF_INT32,
2011 ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2013 ITEM_ARRAY_OF_STRUCT_OF_INT32,
2014 ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2016 ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2017 ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2023 typedef dbus_bool_t (* WriteItemFunc) (DataBlock *block,
2024 DBusTypeWriter *writer);
2025 typedef dbus_bool_t (* ReadItemFunc) (DataBlock *block,
2026 DBusTypeReader *reader);
2032 WriteItemFunc write_item_func;
2033 ReadItemFunc read_item_func;
2036 static CheckMarshalItem items[] = {
2038 ITEM_INT32, write_int32, read_int32 },
2039 { "struct with two int32",
2040 ITEM_STRUCT_OF_INT32, write_struct_of_int32, read_struct_of_int32 },
2041 { "struct with three structs of two int32",
2042 ITEM_STRUCT_OF_STRUCTS, write_struct_of_structs, read_struct_of_structs },
2043 { "struct of two structs of three structs of two int32",
2044 ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2045 write_struct_of_structs_of_structs,
2046 read_struct_of_structs_of_structs },
2048 ITEM_ARRAY_OF_INT32, write_array_of_int32, read_array_of_int32 },
2049 { "empty array of int32",
2050 ITEM_ARRAY_OF_INT32_EMPTY, write_array_of_int32_empty, read_array_of_int32_empty },
2051 { "array of array of int32",
2052 ITEM_ARRAY_OF_ARRAY_OF_INT32,
2053 write_array_of_array_of_int32, read_array_of_array_of_int32 },
2054 { "empty array of array of int32",
2055 ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2056 write_array_of_array_of_int32_empty, read_array_of_array_of_int32_empty },
2057 { "array of array of array of int32",
2058 ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2059 write_array_of_array_of_array_of_int32, read_array_of_array_of_array_of_int32 },
2060 { "struct of array of int32",
2061 ITEM_STRUCT_OF_ARRAY_OF_INT32, write_struct_of_array_of_int32, read_struct_of_array_of_int32 },
2062 { "struct of struct of array of int32",
2063 ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2064 write_struct_of_struct_of_array_of_int32, read_struct_of_struct_of_array_of_int32 },
2065 { "array of struct of int32",
2066 ITEM_ARRAY_OF_STRUCT_OF_INT32, write_array_of_struct_of_int32, read_array_of_struct_of_int32 },
2067 { "array of array of struct of int32",
2068 ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2069 write_array_of_array_of_struct_of_int32, read_array_of_array_of_struct_of_int32 },
2071 { "struct of array of struct of int32",
2072 ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2073 write_struct_of_array_of_struct_of_int32, read_struct_of_array_of_struct_of_int32 },
2074 { "array of struct of array of int32",
2075 ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2076 write_array_of_struct_of_array_of_int32, read_array_of_struct_of_array_of_int32 },
2081 /* Array of items from the above items[]; -1 terminated */
2085 static TestRun runs[] = {
2086 { { ITEM_INVALID } },
2089 { { ITEM_INT32, ITEM_INVALID } },
2090 { { ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2091 { { ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2093 /* STRUCT_OF_INT32 */
2094 { { ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2095 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2096 { { ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2097 { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2098 { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2100 /* STRUCT_OF_STRUCTS */
2101 { { ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2102 { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2103 { { ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2104 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2105 { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2106 { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2108 /* STRUCT_OF_STRUCTS_OF_STRUCTS */
2109 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2110 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2111 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2112 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2113 { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2114 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2116 /* ARRAY_OF_INT32 */
2117 { { ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2118 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2119 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2120 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2121 { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2122 { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2123 { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2124 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2125 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2126 { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2128 /* ARRAY_OF_ARRAY_OF_INT32 */
2129 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2130 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2131 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2132 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2133 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2134 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2135 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2136 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2137 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2138 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2140 /* ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32 */
2141 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2142 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2143 { { 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 } },
2144 { { 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 } },
2145 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2146 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2147 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2148 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2149 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2150 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2152 /* STRUCT_OF_ARRAY_OF_INT32 */
2153 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2154 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2155 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2156 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2157 { { ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2158 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2160 /* STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32 */
2161 { { ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2163 /* ARRAY_OF_STRUCT_OF_INT32 */
2164 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2165 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2166 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2167 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2168 { { ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2169 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2171 /* ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32 */
2172 { { ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2174 /* STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32 */
2175 { { ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2177 /* ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32 */
2178 { { ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2183 perform_one_run (DataBlock *block,
2187 DBusTypeReader reader;
2188 DBusTypeWriter writer;
2190 DataBlockState saved;
2196 _dbus_verbose ("run byteorder %s items ",
2197 byte_order == DBUS_LITTLE_ENDIAN ? "little" : "big");
2199 while (run->items[i] != ITEM_INVALID)
2201 CheckMarshalItem *item = &items[run->items[i]];
2203 _dbus_verbose ("%s ", item->desc);
2206 _dbus_verbose (" = %d items\n", i);
2209 data_block_save (block, &saved);
2211 data_block_init_reader_writer (block,
2216 while (run->items[i] != ITEM_INVALID)
2218 CheckMarshalItem *item = &items[run->items[i]];
2220 _dbus_verbose (">>writing %s\n", item->desc);
2222 if (!(* item->write_item_func) (block, &writer))
2228 while (run->items[i] != ITEM_INVALID)
2230 CheckMarshalItem *item = &items[run->items[i]];
2232 _dbus_verbose (">>data for reading %s\n", item->desc);
2234 _dbus_verbose_bytes_of_string (reader.type_str, 0,
2235 _dbus_string_get_length (reader.type_str));
2236 _dbus_verbose_bytes_of_string (reader.value_str, 0,
2237 _dbus_string_get_length (reader.value_str));
2239 _dbus_verbose (">>reading %s\n", item->desc);
2241 if (!(* item->read_item_func) (block, &reader))
2244 _dbus_type_reader_next (&reader);
2252 data_block_restore (block, &saved);
2257 perform_all_runs (int byte_order,
2266 if (!data_block_init (&block))
2269 if (!_dbus_string_lengthen (&block.signature, initial_offset))
2272 if (!_dbus_string_lengthen (&block.body, initial_offset))
2276 while (i < _DBUS_N_ELEMENTS (runs))
2278 if (!perform_one_run (&block, byte_order, &runs[i]))
2287 data_block_free (&block);
2293 perform_all_items (int byte_order,
2303 if (!data_block_init (&block))
2307 if (!_dbus_string_lengthen (&block.signature, initial_offset))
2310 if (!_dbus_string_lengthen (&block.body, initial_offset))
2313 /* Create a run containing all the items */
2315 while (i < _DBUS_N_ELEMENTS (items))
2317 _dbus_assert (i == items[i].which);
2319 run.items[i] = items[i].which;
2324 run.items[i] = ITEM_INVALID;
2326 if (!perform_one_run (&block, byte_order, &run))
2332 data_block_free (&block);
2338 recursive_marshal_test_iteration (void *data)
2345 if (!perform_all_runs (DBUS_LITTLE_ENDIAN, i))
2347 if (!perform_all_runs (DBUS_BIG_ENDIAN, i))
2349 if (!perform_all_items (DBUS_LITTLE_ENDIAN, i))
2351 if (!perform_all_items (DBUS_BIG_ENDIAN, i))
2360 dbus_bool_t _dbus_marshal_recursive_test (void);
2363 _dbus_marshal_recursive_test (void)
2365 _dbus_test_oom_handling ("recursive marshaling",
2366 recursive_marshal_test_iteration,
2374 main (int argc, char **argv)
2376 _dbus_marshal_recursive_test ();
2382 #endif /* DBUS_BUILD_TESTS */