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
31 #define RECURSIVE_MARSHAL_TRACE 0
33 struct DBusTypeReaderClass
36 dbus_bool_t types_only; /* only iterates over types, not values */
37 void (* recurse) (DBusTypeReader *sub,
38 DBusTypeReader *parent);
39 int (* get_current_type) (DBusTypeReader *reader);
40 void (* next) (DBusTypeReader *reader,
45 first_type_in_signature (const DBusString *str,
50 t = _dbus_string_get_byte (str, pos);
52 if (t == DBUS_STRUCT_BEGIN_CHAR)
53 return DBUS_TYPE_STRUCT;
59 element_type_get_alignment (const DBusString *str,
62 return _dbus_type_get_alignment (first_type_in_signature (str, pos));
66 reader_init (DBusTypeReader *reader,
68 const DBusString *type_str,
70 const DBusString *value_str,
73 reader->byte_order = byte_order;
74 reader->finished = FALSE;
75 reader->type_str = type_str;
76 reader->type_pos = type_pos;
77 reader->value_str = value_str;
78 reader->value_pos = value_pos;
82 base_reader_recurse (DBusTypeReader *sub,
83 DBusTypeReader *parent)
85 /* point subreader at the same place as parent */
95 struct_types_only_reader_recurse (DBusTypeReader *sub,
96 DBusTypeReader *parent)
98 base_reader_recurse (sub, parent);
100 _dbus_assert (_dbus_string_get_byte (sub->type_str,
101 sub->type_pos) == DBUS_STRUCT_BEGIN_CHAR);
107 struct_reader_recurse (DBusTypeReader *sub,
108 DBusTypeReader *parent)
110 struct_types_only_reader_recurse (sub, parent);
112 /* struct has 8 byte alignment */
113 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
117 array_types_only_reader_recurse (DBusTypeReader *sub,
118 DBusTypeReader *parent)
120 base_reader_recurse (sub, parent);
122 /* point type_pos at the array element type */
125 sub->u.array.element_type = first_type_in_signature (sub->type_str,
128 /* Init with values likely to crash things if misused */
129 sub->u.array.start_pos = _DBUS_INT_MAX;
130 sub->u.array.len = _DBUS_INT_MAX;
134 array_reader_recurse (DBusTypeReader *sub,
135 DBusTypeReader *parent)
137 dbus_uint32_t array_len;
140 _dbus_assert (!_dbus_type_reader_array_is_empty (parent));
142 array_types_only_reader_recurse (sub, parent);
144 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
146 _dbus_demarshal_basic_type (sub->value_str,
152 sub->u.array.len = array_len;
154 alignment = element_type_get_alignment (sub->type_str,
157 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
159 sub->u.array.start_pos = sub->value_pos;
161 #if RECURSIVE_MARSHAL_TRACE
162 _dbus_verbose (" type reader %p array start = %d array len = %d array element type = %s\n",
164 sub->u.array.start_pos,
166 _dbus_type_to_string (sub->u.array.element_type));
171 variant_reader_recurse (DBusTypeReader *sub,
172 DBusTypeReader *parent)
176 _dbus_assert (!_dbus_type_reader_array_is_empty (parent));
178 base_reader_recurse (sub, parent);
180 /* Variant is 1 byte sig length (without nul), signature with nul,
181 * padding to 8-boundary, then values
184 sig_len = _dbus_string_get_byte (sub->value_str, sub->value_pos);
186 sub->type_str = sub->value_str;
187 sub->type_pos = sub->value_pos + 1;
189 sub->value_pos = sub->type_pos + sig_len + 1;
191 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
193 #if RECURSIVE_MARSHAL_TRACE
194 _dbus_verbose (" type reader %p variant containing '%s'\n",
196 _dbus_string_get_const_data_len (sub->type_str,
202 base_reader_get_current_type (DBusTypeReader *reader)
206 t = first_type_in_signature (reader->type_str,
213 struct_reader_get_current_type (DBusTypeReader *reader)
217 if (reader->finished)
218 t = DBUS_TYPE_INVALID;
220 t = first_type_in_signature (reader->type_str,
227 array_types_only_reader_get_current_type (DBusTypeReader *reader)
231 if (reader->finished)
232 t = DBUS_TYPE_INVALID;
234 t = reader->u.array.element_type;
240 array_reader_get_current_type (DBusTypeReader *reader)
245 /* return the array element type if elements remain, and
246 * TYPE_INVALID otherwise
249 end_pos = reader->u.array.start_pos + reader->u.array.len;
251 _dbus_assert (reader->value_pos <= end_pos);
252 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
254 if (reader->value_pos < end_pos)
255 t = reader->u.array.element_type;
257 t = DBUS_TYPE_INVALID;
263 skip_one_complete_type (const DBusString *type_str,
266 while (_dbus_string_get_byte (type_str, *type_pos) == DBUS_TYPE_ARRAY)
269 if (_dbus_string_get_byte (type_str, *type_pos) == DBUS_STRUCT_BEGIN_CHAR)
276 switch (_dbus_string_get_byte (type_str, *type_pos))
278 case DBUS_STRUCT_BEGIN_CHAR:
281 case DBUS_STRUCT_END_CHAR:
284 case DBUS_TYPE_INVALID:
285 _dbus_assert_not_reached ("unbalanced parens in signature");
296 skip_array_values (int element_type,
297 const DBusString *value_str,
301 dbus_uint32_t array_len;
305 pos = _DBUS_ALIGN_VALUE (*value_pos, 4);
307 _dbus_demarshal_basic_type (value_str,
313 alignment = _dbus_type_get_alignment (element_type);
315 pos = _DBUS_ALIGN_VALUE (pos, alignment);
317 *value_pos = pos + array_len;
321 base_reader_next (DBusTypeReader *reader,
324 switch (current_type)
326 case DBUS_TYPE_STRUCT:
327 /* Scan forward over the entire container contents */
331 /* Recurse into the struct */
332 _dbus_type_reader_recurse (reader, &sub);
334 /* Skip everything in this subreader */
335 while (_dbus_type_reader_next (&sub))
340 /* Now we are at the end of this container */
341 reader->type_pos = sub.type_pos;
343 if (!reader->klass->types_only)
344 reader->value_pos = sub.value_pos;
348 case DBUS_TYPE_ARRAY:
350 if (!reader->klass->types_only)
351 skip_array_values (first_type_in_signature (reader->type_str,
352 reader->type_pos + 1),
353 reader->value_str, &reader->value_pos, reader->byte_order);
355 skip_one_complete_type (reader->type_str, &reader->type_pos);
360 if (!reader->klass->types_only)
361 _dbus_marshal_skip_basic_type (reader->value_str,
362 current_type, reader->byte_order,
365 reader->type_pos += 1;
371 struct_reader_next (DBusTypeReader *reader,
376 base_reader_next (reader, current_type);
378 /* for STRUCT containers we return FALSE at the end of the struct,
379 * for INVALID we return FALSE at the end of the signature.
380 * In both cases we arrange for get_current_type() to return INVALID
381 * which is defined to happen iff we're at the end (no more next())
383 t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
384 if (t == DBUS_STRUCT_END_CHAR)
386 reader->type_pos += 1;
387 reader->finished = TRUE;
392 array_types_only_reader_next (DBusTypeReader *reader,
395 /* We have one "element" to be iterated over
396 * in each array, which is its element type.
397 * So the finished flag indicates whether we've
398 * iterated over it yet or not.
400 reader->finished = TRUE;
404 array_reader_next (DBusTypeReader *reader,
407 /* Skip one array element */
410 end_pos = reader->u.array.start_pos + reader->u.array.len;
412 _dbus_assert (reader->value_pos < end_pos);
413 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
415 if (reader->u.array.element_type == DBUS_TYPE_STRUCT)
419 /* Recurse into the struct */
420 _dbus_type_reader_recurse (reader, &sub);
422 /* Skip everything in this element */
423 while (_dbus_type_reader_next (&sub))
428 /* Now we are at the end of this element */
429 reader->value_pos = sub.value_pos;
431 else if (reader->u.array.element_type == DBUS_TYPE_ARRAY)
433 skip_array_values (first_type_in_signature (reader->type_str,
434 reader->type_pos + 1),
435 reader->value_str, &reader->value_pos, reader->byte_order);
439 _dbus_marshal_skip_basic_type (reader->value_str,
440 current_type, reader->byte_order,
444 _dbus_assert (reader->value_pos <= end_pos);
446 if (reader->value_pos == end_pos)
448 skip_one_complete_type (reader->type_str,
453 static const DBusTypeReaderClass body_reader_class = {
456 NULL, /* body is always toplevel, so doesn't get recursed into */
457 base_reader_get_current_type,
461 static const DBusTypeReaderClass body_types_only_reader_class = {
464 NULL, /* body is always toplevel, so doesn't get recursed into */
465 base_reader_get_current_type,
469 static const DBusTypeReaderClass struct_reader_class = {
472 struct_reader_recurse,
473 struct_reader_get_current_type,
477 static const DBusTypeReaderClass struct_types_only_reader_class = {
480 struct_types_only_reader_recurse,
481 struct_reader_get_current_type,
485 static const DBusTypeReaderClass array_reader_class = {
488 array_reader_recurse,
489 array_reader_get_current_type,
493 static const DBusTypeReaderClass array_types_only_reader_class = {
496 array_types_only_reader_recurse,
497 array_types_only_reader_get_current_type,
498 array_types_only_reader_next
501 static const DBusTypeReaderClass variant_reader_class = {
504 variant_reader_recurse,
505 base_reader_get_current_type,
510 _dbus_type_reader_init (DBusTypeReader *reader,
512 const DBusString *type_str,
514 const DBusString *value_str,
517 reader->klass = &body_reader_class;
519 reader_init (reader, byte_order, type_str, type_pos,
520 value_str, value_pos);
522 #if RECURSIVE_MARSHAL_TRACE
523 _dbus_verbose (" type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
524 reader, reader->type_pos, reader->value_pos,
525 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
530 _dbus_type_reader_init_types_only (DBusTypeReader *reader,
531 const DBusString *type_str,
534 reader->klass = &body_types_only_reader_class;
536 reader_init (reader, DBUS_COMPILER_BYTE_ORDER /* irrelevant */,
537 type_str, type_pos, NULL, _DBUS_INT_MAX /* crashes if we screw up */);
539 #if RECURSIVE_MARSHAL_TRACE
540 _dbus_verbose (" type reader %p init types only type_pos = %d remaining sig '%s'\n",
541 reader, reader->type_pos,
542 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
547 _dbus_type_reader_get_current_type (DBusTypeReader *reader)
551 t = (* reader->klass->get_current_type) (reader);
553 _dbus_assert (t != DBUS_STRUCT_END_CHAR);
554 _dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR);
557 _dbus_verbose (" type reader %p current type_pos = %d type = %s\n",
558 reader, reader->type_pos,
559 _dbus_type_to_string (t));
566 _dbus_type_reader_array_is_empty (DBusTypeReader *reader)
568 dbus_uint32_t array_len;
571 _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY);
572 _dbus_assert (!reader->klass->types_only);
574 len_pos = _DBUS_ALIGN_VALUE (reader->value_pos, 4);
576 _dbus_demarshal_basic_type (reader->value_str,
582 return array_len == 0;
586 _dbus_type_reader_read_basic (DBusTypeReader *reader,
592 _dbus_assert (!reader->klass->types_only);
594 t = _dbus_type_reader_get_current_type (reader);
596 next = reader->value_pos;
597 _dbus_demarshal_basic_type (reader->value_str,
603 #if RECURSIVE_MARSHAL_TRACE
604 _dbus_verbose (" type reader %p read basic type_pos = %d value_pos = %d next = %d remaining sig '%s'\n",
605 reader, reader->type_pos, reader->value_pos, next,
606 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
611 _dbus_type_reader_read_array_of_basic (DBusTypeReader *reader,
616 _dbus_assert (!reader->klass->types_only);
621 * Initialize a new reader pointing to the first type and
622 * corresponding value that's a child of the current container. It's
623 * an error to call this if the current type is a non-container.
625 * Note that DBusTypeReader traverses values, not types. So if you
626 * have an empty array of array of int, you can't recurse into it. You
627 * can only recurse into each element.
629 * @param reader the reader
630 * @param sub a reader to init pointing to the first child
633 _dbus_type_reader_recurse (DBusTypeReader *reader,
638 t = first_type_in_signature (reader->type_str, reader->type_pos);
642 case DBUS_TYPE_STRUCT:
643 if (reader->klass->types_only)
644 sub->klass = &struct_types_only_reader_class;
646 sub->klass = &struct_reader_class;
648 case DBUS_TYPE_ARRAY:
649 if (reader->klass->types_only)
650 sub->klass = &array_types_only_reader_class;
652 sub->klass = &array_reader_class;
654 case DBUS_TYPE_VARIANT:
655 if (reader->klass->types_only)
656 _dbus_assert_not_reached ("can't recurse into variant typecode");
658 sub->klass = &variant_reader_class;
661 _dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t));
662 #ifndef DBUS_DISABLE_CHECKS
663 if (t == DBUS_TYPE_INVALID)
664 _dbus_warn ("You can't recurse into an empty array or off the end of a message body\n");
665 #endif /* DBUS_DISABLE_CHECKS */
667 _dbus_assert_not_reached ("don't yet handle recursing into this type");
670 (* sub->klass->recurse) (sub, reader);
672 #if RECURSIVE_MARSHAL_TRACE
673 _dbus_verbose (" type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
674 sub, sub->type_pos, sub->value_pos,
675 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
680 * Skip to the next value on this "level". e.g. the next field in a
681 * struct, the next value in an array, the next key or value in a
682 * dict. Returns FALSE at the end of the current container.
684 * @param reader the reader
685 * @returns FALSE if nothing more to read at or below this level
688 _dbus_type_reader_next (DBusTypeReader *reader)
692 t = _dbus_type_reader_get_current_type (reader);
694 #if RECURSIVE_MARSHAL_TRACE
695 _dbus_verbose (" type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
696 reader, reader->type_pos, reader->value_pos,
697 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
698 _dbus_type_to_string (t));
701 if (t == DBUS_TYPE_INVALID)
704 (* reader->klass->next) (reader, t);
706 #if RECURSIVE_MARSHAL_TRACE
707 _dbus_verbose (" type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
708 reader, reader->type_pos, reader->value_pos,
709 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
710 _dbus_type_to_string (_dbus_type_reader_get_current_type (reader)));
713 return _dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID;
727 _dbus_type_writer_init (DBusTypeWriter *writer,
729 DBusString *type_str,
731 DBusString *value_str,
734 writer->byte_order = byte_order;
735 writer->type_str = type_str;
736 writer->type_pos = type_pos;
737 writer->value_str = value_str;
738 writer->value_pos = value_pos;
739 writer->container_type = DBUS_TYPE_INVALID;
740 writer->type_pos_is_expectation = FALSE;
742 #if RECURSIVE_MARSHAL_TRACE
743 _dbus_verbose ("writer %p init remaining sig '%s'\n", writer,
744 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
749 _dbus_type_writer_write_basic_no_typecode (DBusTypeWriter *writer,
756 old_value_len = _dbus_string_get_length (writer->value_str);
758 if (!_dbus_marshal_basic_type (writer->value_str,
765 bytes_written = _dbus_string_get_length (writer->value_str) - old_value_len;
767 writer->value_pos += bytes_written;
772 /* If our parent is an array, things are a little bit complicated.
774 * The parent must have a complete element type, such as
775 * "i" or "aai" or "(ii)" or "a(ii)". There can't be
776 * unclosed parens, or an "a" with no following type.
778 * To recurse, the only allowed operation is to recurse into the
779 * first type in the element type. So for "i" you can't recurse, for
780 * "ai" you can recurse into the array, for "(ii)" you can recurse
783 * If you recurse into the array for "ai", then you must specify
784 * "i" for the element type of the array you recurse into.
786 * While inside an array at any level, we need to avoid writing to
787 * type_str, since the type only appears once for the whole array,
788 * it does not appear for each array element.
790 * While inside an array type_pos points to the expected next
791 * typecode, rather than the next place we could write a typecode.
794 writer_recurse_init_and_check (DBusTypeWriter *writer,
798 _dbus_type_writer_init (sub,
805 sub->container_type = container_type;
807 if (writer->type_pos_is_expectation ||
808 (sub->container_type == DBUS_TYPE_ARRAY || sub->container_type == DBUS_TYPE_VARIANT))
809 sub->type_pos_is_expectation = TRUE;
811 sub->type_pos_is_expectation = FALSE;
813 #ifndef DBUS_DISABLE_CHECKS
814 if (writer->type_pos_is_expectation)
818 expected = first_type_in_signature (writer->type_str, writer->type_pos);
820 if (expected != sub->container_type)
822 _dbus_warn ("Writing an element of type %s, but the expected type here is %s\n",
823 _dbus_type_to_string (sub->container_type),
824 _dbus_type_to_string (expected));
825 _dbus_assert_not_reached ("bad array element or variant content written");
828 #endif /* DBUS_DISABLE_CHECKS */
830 #if RECURSIVE_MARSHAL_TRACE
831 _dbus_verbose (" type writer %p recurse parent type_pos = %d value_pos = %d is_expectation = %d container_type = %s remaining sig '%s'\n",
832 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
833 _dbus_type_to_string (writer->container_type),
834 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
835 _dbus_verbose (" type writer %p recurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
836 sub, sub->type_pos, sub->value_pos,
837 sub->type_pos_is_expectation,
838 _dbus_type_to_string (sub->container_type));
843 write_or_verify_typecode (DBusTypeWriter *writer,
846 /* A subwriter inside an array or variant will have type_pos
847 * pointing to the expected typecode; a writer not inside an array
848 * or variant has type_pos pointing to the next place to insert a
851 #if RECURSIVE_MARSHAL_TRACE
852 _dbus_verbose (" type writer %p write_or_verify start type_pos = %d remaining sig '%s'\n",
853 writer, writer->type_pos,
854 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
857 if (writer->type_pos_is_expectation)
859 #ifndef DBUS_DISABLE_CHECKS
863 expected = _dbus_string_get_byte (writer->type_str, writer->type_pos);
865 if (expected != typecode)
867 _dbus_warn ("Array or Variant type requires that type %s be written, but %s was written\n",
868 _dbus_type_to_string (expected), _dbus_type_to_string (typecode));
869 _dbus_assert_not_reached ("bad type inserted somewhere inside an array or variant");
872 #endif /* DBUS_DISABLE_CHECKS */
874 /* if immediately inside an array we'd always be appending an element,
875 * so the expected type doesn't change; if inside a struct or something
876 * below an array, we need to move through said struct or something.
878 if (writer->container_type != DBUS_TYPE_ARRAY)
879 writer->type_pos += 1;
883 if (!_dbus_string_insert_byte (writer->type_str,
888 writer->type_pos += 1;
891 #if RECURSIVE_MARSHAL_TRACE
892 _dbus_verbose (" type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
893 writer, writer->type_pos,
894 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
901 _dbus_type_writer_recurse_struct (DBusTypeWriter *writer,
904 writer_recurse_init_and_check (writer, DBUS_TYPE_STRUCT, sub);
906 /* Ensure that we'll be able to add alignment padding and the typecode */
907 if (!_dbus_string_alloc_space (sub->value_str, 8))
910 if (!_dbus_string_alloc_space (sub->type_str, 1))
913 if (!write_or_verify_typecode (sub, DBUS_STRUCT_BEGIN_CHAR))
914 _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
916 if (!_dbus_string_insert_bytes (sub->value_str,
918 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
920 _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
921 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
927 _dbus_type_writer_recurse_array (DBusTypeWriter *writer,
928 const char *element_type,
931 int element_type_len;
932 DBusString element_type_str;
933 dbus_uint32_t value = 0;
938 writer_recurse_init_and_check (writer, DBUS_TYPE_ARRAY, sub);
940 _dbus_string_init_const (&element_type_str, element_type);
941 element_type_len = _dbus_string_get_length (&element_type_str);
943 #ifndef DBUS_DISABLE_CHECKS
944 if (writer->container_type == DBUS_TYPE_ARRAY)
946 if (!_dbus_string_equal_substring (&element_type_str, 0, element_type_len,
947 writer->type_str, writer->u.array.element_type_pos + 1))
949 _dbus_warn ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
951 _dbus_assert_not_reached ("incompatible type for child array");
954 #endif /* DBUS_DISABLE_CHECKS */
956 /* 4 bytes for the array length and 4 bytes possible padding */
957 if (!_dbus_string_alloc_space (sub->value_str, 8))
960 sub->type_pos += 1; /* move to point to the element type, since type_pos
961 * should be the expected type for further writes
963 sub->u.array.element_type_pos = sub->type_pos;
965 if (!writer->type_pos_is_expectation)
967 /* sub is a toplevel/outermost array so we need to write the type data */
969 /* alloc space for array typecode, element signature, possible 7
972 if (!_dbus_string_alloc_space (writer->type_str, 1 + element_type_len + 7))
975 if (!_dbus_string_insert_byte (writer->type_str,
978 _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
980 if (!_dbus_string_copy (&element_type_str, 0,
981 sub->type_str, sub->u.array.element_type_pos))
982 _dbus_assert_not_reached ("should not have failed to insert array element typecodes");
985 /* If the parent is an array, we hold type_pos pointing at the array element type;
986 * otherwise advance it to reflect the array value we just recursed into
988 if (writer->container_type != DBUS_TYPE_ARRAY)
989 writer->type_pos += 1 + element_type_len;
991 _dbus_assert (writer->type_pos_is_expectation); /* because it's an array */
993 /* Write the length */
994 sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
996 if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
998 _dbus_assert_not_reached ("should not have failed to insert array len");
1000 _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
1002 /* Write alignment padding for array elements */
1003 _dbus_string_init_const (&str, element_type);
1004 alignment = element_type_get_alignment (&str, 0);
1006 aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
1007 if (aligned != sub->value_pos)
1009 if (!_dbus_string_insert_bytes (sub->value_str,
1011 aligned - sub->value_pos,
1013 _dbus_assert_not_reached ("should not have failed to insert alignment padding");
1015 sub->value_pos = aligned;
1017 sub->u.array.start_pos = sub->value_pos;
1019 _dbus_assert (sub->u.array.start_pos == sub->value_pos);
1020 _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
1022 #if RECURSIVE_MARSHAL_TRACE
1023 _dbus_verbose (" type writer %p recurse array done remaining sig '%s'\n", sub,
1024 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
1030 /* Variant value will normally have:
1031 * 1 byte signature length not including nul
1032 * signature typecodes (nul terminated)
1033 * padding to 8-boundary
1034 * body according to signature
1036 * The signature string can only have a single type
1037 * in it but that type may be complex/recursive.
1039 * So a typical variant type with the integer 3 will have these
1041 * 0x1 'i' '\0' [padding to 8-boundary] 0x0 0x0 0x0 0x3
1043 * For an array of 4-byte types stuffed into variants, the padding to
1044 * 8-boundary is only the 1 byte that is required for the 4-boundary
1045 * anyhow for all array elements after the first one. And for single
1046 * variants in isolation, wasting a few bytes is hardly a big deal.
1048 * The main world of hurt for writing out a variant is that the type
1049 * string is the same string as the value string. Which means
1050 * inserting to the type string will move the value_pos; and it means
1051 * that inserting to the type string could break type alignment.
1053 * This type alignment issue is why the body of the variant is always
1054 * 8-aligned. Then we know that re-8-aligning the start of the body
1055 * will always correctly align the full contents of the variant type.
1058 _dbus_type_writer_recurse_variant (DBusTypeWriter *writer,
1059 const char *contained_type,
1060 DBusTypeWriter *sub)
1062 int contained_type_len;
1063 DBusString contained_type_str;
1065 writer_recurse_init_and_check (writer, DBUS_TYPE_VARIANT, sub);
1067 _dbus_string_init_const (&contained_type_str, contained_type);
1069 contained_type_len = _dbus_string_get_length (&contained_type_str);
1071 /* Allocate space for the worst case, which is 1 byte sig
1072 * length, nul byte at end of sig, and 7 bytes padding to
1075 if (!_dbus_string_alloc_space (sub->value_str, contained_type_len + 9))
1078 /* write VARIANT typecode to the parent's type string */
1079 if (!write_or_verify_typecode (sub, DBUS_TYPE_VARIANT))
1082 if (!_dbus_string_insert_byte (sub->value_str,
1084 contained_type_len))
1085 _dbus_assert_not_reached ("should not have failed to insert variant type sig len");
1087 sub->value_pos += 1;
1089 /* Here we switch over to the expected type sig we're about to write */
1090 sub->type_str = sub->value_str;
1091 sub->type_pos = sub->value_pos;
1093 if (!_dbus_string_copy (&contained_type_str, 0,
1094 sub->value_str, sub->value_pos))
1095 _dbus_assert_not_reached ("should not have failed to insert variant type sig");
1097 sub->value_pos += contained_type_len;
1099 if (!_dbus_string_insert_byte (sub->value_str,
1102 _dbus_assert_not_reached ("should not have failed to insert variant type nul termination");
1104 sub->value_pos += 1;
1106 if (!_dbus_string_insert_bytes (sub->value_str,
1108 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
1110 _dbus_assert_not_reached ("should not have failed to insert alignment padding for variant body");
1111 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
1117 _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
1118 DBusTypeWriter *sub)
1120 _dbus_assert (sub->type_pos > 0); /* can't be recursed if this fails */
1122 /* type_pos_is_expectation never gets unset once set, or we'd get all hosed */
1123 _dbus_assert (!writer->type_pos_is_expectation ||
1124 (writer->type_pos_is_expectation && sub->type_pos_is_expectation));
1126 #if RECURSIVE_MARSHAL_TRACE
1127 _dbus_verbose (" type writer %p unrecurse type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
1128 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
1129 _dbus_type_to_string (writer->container_type));
1130 _dbus_verbose (" type writer %p unrecurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
1131 sub, sub->type_pos, sub->value_pos,
1132 sub->type_pos_is_expectation,
1133 _dbus_type_to_string (sub->container_type));
1136 if (sub->container_type == DBUS_TYPE_STRUCT)
1138 if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
1141 else if (sub->container_type == DBUS_TYPE_ARRAY)
1145 /* Set the array length */
1146 len = sub->value_pos - sub->u.array.start_pos;
1147 _dbus_marshal_set_uint32 (sub->value_str,
1149 sub->u.array.len_pos,
1151 #if RECURSIVE_MARSHAL_TRACE
1152 _dbus_verbose (" filled in sub array len to %u at len_pos %d\n",
1153 len, sub->u.array.len_pos);
1157 /* Now get type_pos right for the parent writer. Here are the cases:
1159 * Cases !writer->type_pos_is_expectation:
1160 * (in these cases we want to update to the new insertion point)
1162 * - if we recursed into a STRUCT then we didn't know in advance
1163 * what the types in the struct would be; so we have to fill in
1164 * that information now.
1165 * writer->type_pos = sub->type_pos
1167 * - if we recursed into anything else, we knew the full array
1168 * type, or knew the single typecode marking VARIANT, so
1169 * writer->type_pos is already correct.
1170 * writer->type_pos should remain as-is
1172 * - note that the parent is never an ARRAY or VARIANT, if it were
1173 * then type_pos_is_expectation would be TRUE. The parent
1174 * is thus known to be a toplevel or STRUCT.
1176 * Cases where writer->type_pos_is_expectation:
1177 * (in these cases we want to update to next expected type to write)
1179 * - we recursed from STRUCT into STRUCT and we didn't increment
1180 * type_pos in the parent just to stay consistent with the
1181 * !writer->type_pos_is_expectation case (though we could
1182 * special-case this in recurse_struct instead if we wanted)
1183 * writer->type_pos = sub->type_pos
1185 * - we recursed from STRUCT into ARRAY or VARIANT and type_pos
1186 * for parent should have been incremented already
1187 * writer->type_pos should remain as-is
1189 * - we recursed from ARRAY into a sub-element, so type_pos in the
1190 * parent is the element type and should remain the element type
1191 * for the benefit of the next child element
1192 * writer->type_pos should remain as-is
1194 * - we recursed from VARIANT into its value, so type_pos in the
1195 * parent makes no difference since there's only one value
1196 * and we just finished writing it and won't use type_pos again
1197 * writer->type_pos should remain as-is
1199 if (sub->container_type == DBUS_TYPE_STRUCT &&
1200 (writer->container_type == DBUS_TYPE_STRUCT ||
1201 writer->container_type == DBUS_TYPE_INVALID))
1203 /* Advance the parent to the next struct field */
1204 writer->type_pos = sub->type_pos;
1207 writer->value_pos = sub->value_pos;
1209 #if RECURSIVE_MARSHAL_TRACE
1210 _dbus_verbose (" type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
1211 writer, writer->type_pos, writer->value_pos,
1212 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
1219 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
1225 /* First ensure that our type realloc will succeed */
1226 if (!_dbus_string_alloc_space (writer->type_str, 1))
1231 if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
1234 if (!write_or_verify_typecode (writer, type))
1235 _dbus_assert_not_reached ("failed to write typecode after prealloc");
1240 #if RECURSIVE_MARSHAL_TRACE
1241 _dbus_verbose (" type writer %p basic type_pos = %d value_pos = %d is_expectation = %d\n",
1242 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation);
1249 _dbus_type_writer_write_array (DBusTypeWriter *writer,
1258 /** @} */ /* end of DBusMarshal group */
1260 #ifdef DBUS_BUILD_TESTS
1261 #include "dbus-test.h"
1262 #include "dbus-list.h"
1268 DBusString signature;
1279 data_block_init (DataBlock *block)
1281 if (!_dbus_string_init (&block->signature))
1284 if (!_dbus_string_init (&block->body))
1286 _dbus_string_free (&block->signature);
1294 data_block_free (DataBlock *block)
1296 _dbus_string_free (&block->signature);
1297 _dbus_string_free (&block->body);
1301 data_block_save (DataBlock *block,
1302 DataBlockState *state)
1304 state->saved_sig_len = _dbus_string_get_length (&block->signature);
1305 state->saved_body_len = _dbus_string_get_length (&block->body);
1309 data_block_restore (DataBlock *block,
1310 DataBlockState *state)
1312 /* These set_length should be shortening things so should always work */
1314 if (!_dbus_string_set_length (&block->signature,
1315 state->saved_sig_len))
1316 _dbus_assert_not_reached ("could not restore signature length");
1318 if (!_dbus_string_set_length (&block->body,
1319 state->saved_body_len))
1320 _dbus_assert_not_reached ("could not restore body length");
1324 data_block_init_reader_writer (DataBlock *block,
1326 DBusTypeReader *reader,
1327 DBusTypeWriter *writer)
1329 _dbus_type_reader_init (reader,
1332 _dbus_string_get_length (&block->signature),
1334 _dbus_string_get_length (&block->body));
1336 _dbus_type_writer_init (writer,
1339 _dbus_string_get_length (&block->signature),
1341 _dbus_string_get_length (&block->body));
1345 real_check_expected_type (DBusTypeReader *reader,
1347 const char *funcname,
1352 t = _dbus_type_reader_get_current_type (reader);
1356 _dbus_warn ("Read type %s while expecting %s at %s line %d\n",
1357 _dbus_type_to_string (t),
1358 _dbus_type_to_string (expected),
1365 #define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__)
1367 #define NEXT_EXPECTING_TRUE(reader) do { if (!_dbus_type_reader_next (reader)) \
1369 _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d\n", \
1370 _DBUS_FUNCTION_NAME, __LINE__); \
1371 _dbus_assert_not_reached ("test failed"); \
1375 #define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader)) \
1377 _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d\n", \
1378 _DBUS_FUNCTION_NAME, __LINE__); \
1379 _dbus_assert_not_reached ("test failed"); \
1381 check_expected_type (reader, DBUS_TYPE_INVALID); \
1384 #define SAMPLE_INT32 12345678
1385 #define SAMPLE_INT32_ALTERNATE 53781429
1387 write_int32 (DataBlock *block,
1388 DBusTypeWriter *writer)
1390 dbus_int32_t v = SAMPLE_INT32;
1392 return _dbus_type_writer_write_basic (writer,
1398 read_int32 (DataBlock *block,
1399 DBusTypeReader *reader)
1403 check_expected_type (reader, DBUS_TYPE_INT32);
1405 _dbus_type_reader_read_basic (reader,
1406 (dbus_int32_t*) &v);
1408 _dbus_assert (v == SAMPLE_INT32);
1414 write_struct_of_int32 (DataBlock *block,
1415 DBusTypeWriter *writer)
1418 DataBlockState saved;
1421 data_block_save (block, &saved);
1423 if (!_dbus_type_writer_recurse_struct (writer,
1428 if (!_dbus_type_writer_write_basic (&sub,
1432 data_block_restore (block, &saved);
1436 v = SAMPLE_INT32_ALTERNATE;
1437 if (!_dbus_type_writer_write_basic (&sub,
1441 data_block_restore (block, &saved);
1445 if (!_dbus_type_writer_unrecurse (writer, &sub))
1447 data_block_restore (block, &saved);
1455 read_struct_of_int32 (DataBlock *block,
1456 DBusTypeReader *reader)
1461 check_expected_type (reader, DBUS_TYPE_STRUCT);
1463 _dbus_type_reader_recurse (reader, &sub);
1465 check_expected_type (&sub, DBUS_TYPE_INT32);
1467 _dbus_type_reader_read_basic (&sub,
1468 (dbus_int32_t*) &v);
1470 _dbus_assert (v == SAMPLE_INT32);
1472 NEXT_EXPECTING_TRUE (&sub);
1473 check_expected_type (&sub, DBUS_TYPE_INT32);
1475 _dbus_type_reader_read_basic (&sub,
1476 (dbus_int32_t*) &v);
1478 _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1480 NEXT_EXPECTING_FALSE (&sub);
1486 write_struct_of_structs (DataBlock *block,
1487 DBusTypeWriter *writer)
1489 DataBlockState saved;
1492 data_block_save (block, &saved);
1494 if (!_dbus_type_writer_recurse_struct (writer,
1498 if (!write_struct_of_int32 (block, &sub))
1500 data_block_restore (block, &saved);
1503 if (!write_struct_of_int32 (block, &sub))
1505 data_block_restore (block, &saved);
1508 if (!write_struct_of_int32 (block, &sub))
1510 data_block_restore (block, &saved);
1514 if (!_dbus_type_writer_unrecurse (writer, &sub))
1516 data_block_restore (block, &saved);
1524 read_struct_of_structs (DataBlock *block,
1525 DBusTypeReader *reader)
1529 check_expected_type (reader, DBUS_TYPE_STRUCT);
1531 _dbus_type_reader_recurse (reader, &sub);
1533 if (!read_struct_of_int32 (block, &sub))
1536 NEXT_EXPECTING_TRUE (&sub);
1537 if (!read_struct_of_int32 (block, &sub))
1540 NEXT_EXPECTING_TRUE (&sub);
1541 if (!read_struct_of_int32 (block, &sub))
1544 NEXT_EXPECTING_FALSE (&sub);
1550 write_struct_of_structs_of_structs (DataBlock *block,
1551 DBusTypeWriter *writer)
1553 DataBlockState saved;
1556 data_block_save (block, &saved);
1558 if (!_dbus_type_writer_recurse_struct (writer,
1562 if (!write_struct_of_structs (block, &sub))
1564 data_block_restore (block, &saved);
1567 if (!write_struct_of_structs (block, &sub))
1569 data_block_restore (block, &saved);
1573 if (!_dbus_type_writer_unrecurse (writer, &sub))
1575 data_block_restore (block, &saved);
1583 read_struct_of_structs_of_structs (DataBlock *block,
1584 DBusTypeReader *reader)
1588 check_expected_type (reader, DBUS_TYPE_STRUCT);
1590 _dbus_type_reader_recurse (reader, &sub);
1592 if (!read_struct_of_structs (block, &sub))
1595 NEXT_EXPECTING_TRUE (&sub);
1596 if (!read_struct_of_structs (block, &sub))
1599 NEXT_EXPECTING_FALSE (&sub);
1605 write_array_of_int32 (DataBlock *block,
1606 DBusTypeWriter *writer)
1609 DataBlockState saved;
1612 data_block_save (block, &saved);
1614 if (!_dbus_type_writer_recurse_array (writer,
1615 DBUS_TYPE_INT32_AS_STRING,
1619 v = SAMPLE_INT32_ALTERNATE;
1620 if (!_dbus_type_writer_write_basic (&sub,
1624 data_block_restore (block, &saved);
1629 if (!_dbus_type_writer_write_basic (&sub,
1633 data_block_restore (block, &saved);
1638 if (!_dbus_type_writer_write_basic (&sub,
1642 data_block_restore (block, &saved);
1646 if (!_dbus_type_writer_unrecurse (writer, &sub))
1648 data_block_restore (block, &saved);
1656 read_array_of_int32 (DataBlock *block,
1657 DBusTypeReader *reader)
1662 check_expected_type (reader, DBUS_TYPE_ARRAY);
1664 _dbus_type_reader_recurse (reader, &sub);
1666 check_expected_type (&sub, DBUS_TYPE_INT32);
1668 _dbus_type_reader_read_basic (&sub,
1669 (dbus_int32_t*) &v);
1671 _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1673 NEXT_EXPECTING_TRUE (&sub);
1674 check_expected_type (&sub, DBUS_TYPE_INT32);
1676 _dbus_type_reader_read_basic (&sub,
1677 (dbus_int32_t*) &v);
1679 _dbus_assert (v == SAMPLE_INT32);
1681 NEXT_EXPECTING_TRUE (&sub);
1682 check_expected_type (&sub, DBUS_TYPE_INT32);
1684 _dbus_type_reader_read_basic (&sub,
1685 (dbus_int32_t*) &v);
1687 _dbus_assert (v == SAMPLE_INT32);
1689 NEXT_EXPECTING_FALSE (&sub);
1696 write_array_of_int32_empty (DataBlock *block,
1697 DBusTypeWriter *writer)
1699 DataBlockState saved;
1702 data_block_save (block, &saved);
1704 if (!_dbus_type_writer_recurse_array (writer,
1705 DBUS_TYPE_INT32_AS_STRING,
1709 if (!_dbus_type_writer_unrecurse (writer, &sub))
1711 data_block_restore (block, &saved);
1719 read_array_of_int32_empty (DataBlock *block,
1720 DBusTypeReader *reader)
1722 check_expected_type (reader, DBUS_TYPE_ARRAY);
1724 /* We are iterating over values not types. Thus we can't recurse
1727 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1733 write_array_of_array_of_int32 (DataBlock *block,
1734 DBusTypeWriter *writer)
1736 DataBlockState saved;
1739 data_block_save (block, &saved);
1741 if (!_dbus_type_writer_recurse_array (writer,
1742 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1746 if (!write_array_of_int32 (block, &sub))
1748 data_block_restore (block, &saved);
1752 if (!write_array_of_int32 (block, &sub))
1754 data_block_restore (block, &saved);
1758 if (!write_array_of_int32_empty (block, &sub))
1760 data_block_restore (block, &saved);
1764 if (!write_array_of_int32 (block, &sub))
1766 data_block_restore (block, &saved);
1770 if (!_dbus_type_writer_unrecurse (writer, &sub))
1772 data_block_restore (block, &saved);
1780 read_array_of_array_of_int32 (DataBlock *block,
1781 DBusTypeReader *reader)
1785 check_expected_type (reader, DBUS_TYPE_ARRAY);
1787 _dbus_type_reader_recurse (reader, &sub);
1789 if (!read_array_of_int32 (block, &sub))
1792 NEXT_EXPECTING_TRUE (&sub);
1793 if (!read_array_of_int32 (block, &sub))
1796 NEXT_EXPECTING_TRUE (&sub);
1797 if (!read_array_of_int32_empty (block, &sub))
1800 NEXT_EXPECTING_TRUE (&sub);
1801 if (!read_array_of_int32 (block, &sub))
1804 NEXT_EXPECTING_FALSE (&sub);
1811 write_array_of_array_of_int32_empty (DataBlock *block,
1812 DBusTypeWriter *writer)
1814 DataBlockState saved;
1817 data_block_save (block, &saved);
1819 if (!_dbus_type_writer_recurse_array (writer,
1820 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1824 if (!_dbus_type_writer_unrecurse (writer, &sub))
1826 data_block_restore (block, &saved);
1834 read_array_of_array_of_int32_empty (DataBlock *block,
1835 DBusTypeReader *reader)
1837 check_expected_type (reader, DBUS_TYPE_ARRAY);
1839 /* We are iterating over values, not types. Thus
1840 * we can't recurse in here.
1843 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1849 write_array_of_array_of_array_of_int32 (DataBlock *block,
1850 DBusTypeWriter *writer)
1852 DataBlockState saved;
1855 data_block_save (block, &saved);
1857 if (!_dbus_type_writer_recurse_array (writer,
1858 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1862 if (!write_array_of_array_of_int32 (block, &sub))
1864 data_block_restore (block, &saved);
1868 if (!write_array_of_array_of_int32 (block, &sub))
1870 data_block_restore (block, &saved);
1874 if (!write_array_of_array_of_int32_empty (block, &sub))
1876 data_block_restore (block, &saved);
1880 if (!_dbus_type_writer_unrecurse (writer, &sub))
1882 data_block_restore (block, &saved);
1890 read_array_of_array_of_array_of_int32 (DataBlock *block,
1891 DBusTypeReader *reader)
1895 check_expected_type (reader, DBUS_TYPE_ARRAY);
1897 _dbus_type_reader_recurse (reader, &sub);
1899 if (!read_array_of_array_of_int32 (block, &sub))
1902 NEXT_EXPECTING_TRUE (&sub);
1903 if (!read_array_of_array_of_int32 (block, &sub))
1906 NEXT_EXPECTING_TRUE (&sub);
1907 if (!read_array_of_array_of_int32_empty (block, &sub))
1910 NEXT_EXPECTING_FALSE (&sub);
1916 write_struct_of_array_of_int32 (DataBlock *block,
1917 DBusTypeWriter *writer)
1919 DataBlockState saved;
1922 data_block_save (block, &saved);
1924 if (!_dbus_type_writer_recurse_struct (writer,
1928 if (!write_array_of_int32 (block, &sub))
1930 data_block_restore (block, &saved);
1934 if (!write_array_of_int32_empty (block, &sub))
1936 data_block_restore (block, &saved);
1940 if (!_dbus_type_writer_unrecurse (writer, &sub))
1942 data_block_restore (block, &saved);
1950 read_struct_of_array_of_int32 (DataBlock *block,
1951 DBusTypeReader *reader)
1955 check_expected_type (reader, DBUS_TYPE_STRUCT);
1957 _dbus_type_reader_recurse (reader, &sub);
1959 check_expected_type (&sub, DBUS_TYPE_ARRAY);
1961 if (!read_array_of_int32 (block, &sub))
1964 NEXT_EXPECTING_TRUE (&sub);
1965 if (!read_array_of_int32_empty (block, &sub))
1968 NEXT_EXPECTING_FALSE (&sub);
1974 write_struct_of_struct_of_array_of_int32 (DataBlock *block,
1975 DBusTypeWriter *writer)
1977 DataBlockState saved;
1980 data_block_save (block, &saved);
1982 if (!_dbus_type_writer_recurse_struct (writer,
1986 if (!write_struct_of_array_of_int32 (block, &sub))
1988 data_block_restore (block, &saved);
1991 if (!write_struct_of_array_of_int32 (block, &sub))
1993 data_block_restore (block, &saved);
1996 if (!write_struct_of_array_of_int32 (block, &sub))
1998 data_block_restore (block, &saved);
2002 if (!_dbus_type_writer_unrecurse (writer, &sub))
2004 data_block_restore (block, &saved);
2012 read_struct_of_struct_of_array_of_int32 (DataBlock *block,
2013 DBusTypeReader *reader)
2017 check_expected_type (reader, DBUS_TYPE_STRUCT);
2019 _dbus_type_reader_recurse (reader, &sub);
2021 if (!read_struct_of_array_of_int32 (block, &sub))
2024 NEXT_EXPECTING_TRUE (&sub);
2025 if (!read_struct_of_array_of_int32 (block, &sub))
2028 NEXT_EXPECTING_TRUE (&sub);
2029 if (!read_struct_of_array_of_int32 (block, &sub))
2032 NEXT_EXPECTING_FALSE (&sub);
2038 write_array_of_struct_of_int32 (DataBlock *block,
2039 DBusTypeWriter *writer)
2041 DataBlockState saved;
2044 data_block_save (block, &saved);
2046 if (!_dbus_type_writer_recurse_array (writer,
2047 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2048 DBUS_TYPE_INT32_AS_STRING
2049 DBUS_TYPE_INT32_AS_STRING
2050 DBUS_STRUCT_END_CHAR_AS_STRING,
2054 if (!write_struct_of_int32 (block, &sub))
2056 data_block_restore (block, &saved);
2060 if (!write_struct_of_int32 (block, &sub))
2062 data_block_restore (block, &saved);
2066 if (!write_struct_of_int32 (block, &sub))
2068 data_block_restore (block, &saved);
2072 if (!_dbus_type_writer_unrecurse (writer, &sub))
2074 data_block_restore (block, &saved);
2082 read_array_of_struct_of_int32 (DataBlock *block,
2083 DBusTypeReader *reader)
2087 check_expected_type (reader, DBUS_TYPE_ARRAY);
2089 _dbus_type_reader_recurse (reader, &sub);
2091 check_expected_type (&sub, DBUS_TYPE_STRUCT);
2093 if (!read_struct_of_int32 (block, &sub))
2096 NEXT_EXPECTING_TRUE (&sub);
2098 if (!read_struct_of_int32 (block, &sub))
2101 NEXT_EXPECTING_TRUE (&sub);
2103 if (!read_struct_of_int32 (block, &sub))
2106 NEXT_EXPECTING_FALSE (&sub);
2113 write_array_of_array_of_struct_of_int32 (DataBlock *block,
2114 DBusTypeWriter *writer)
2116 DataBlockState saved;
2119 data_block_save (block, &saved);
2121 if (!_dbus_type_writer_recurse_array (writer,
2122 DBUS_TYPE_ARRAY_AS_STRING
2123 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2124 DBUS_TYPE_INT32_AS_STRING
2125 DBUS_TYPE_INT32_AS_STRING
2126 DBUS_STRUCT_END_CHAR_AS_STRING,
2130 if (!write_array_of_struct_of_int32 (block, &sub))
2132 data_block_restore (block, &saved);
2136 if (!write_array_of_struct_of_int32 (block, &sub))
2138 data_block_restore (block, &saved);
2142 if (!write_array_of_struct_of_int32 (block, &sub))
2144 data_block_restore (block, &saved);
2148 if (!_dbus_type_writer_unrecurse (writer, &sub))
2150 data_block_restore (block, &saved);
2158 read_array_of_array_of_struct_of_int32 (DataBlock *block,
2159 DBusTypeReader *reader)
2163 check_expected_type (reader, DBUS_TYPE_ARRAY);
2165 _dbus_type_reader_recurse (reader, &sub);
2167 check_expected_type (&sub, DBUS_TYPE_ARRAY);
2169 if (!read_array_of_struct_of_int32 (block, &sub))
2172 NEXT_EXPECTING_TRUE (&sub);
2174 if (!read_array_of_struct_of_int32 (block, &sub))
2177 NEXT_EXPECTING_TRUE (&sub);
2179 if (!read_array_of_struct_of_int32 (block, &sub))
2182 NEXT_EXPECTING_FALSE (&sub);
2188 write_struct_of_array_of_struct_of_int32 (DataBlock *block,
2189 DBusTypeWriter *writer)
2191 DataBlockState saved;
2194 data_block_save (block, &saved);
2196 if (!_dbus_type_writer_recurse_struct (writer,
2200 if (!write_array_of_struct_of_int32 (block, &sub))
2202 data_block_restore (block, &saved);
2205 if (!write_array_of_struct_of_int32 (block, &sub))
2207 data_block_restore (block, &saved);
2210 if (!write_array_of_struct_of_int32 (block, &sub))
2212 data_block_restore (block, &saved);
2216 if (!_dbus_type_writer_unrecurse (writer, &sub))
2218 data_block_restore (block, &saved);
2226 read_struct_of_array_of_struct_of_int32 (DataBlock *block,
2227 DBusTypeReader *reader)
2231 check_expected_type (reader, DBUS_TYPE_STRUCT);
2233 _dbus_type_reader_recurse (reader, &sub);
2235 if (!read_array_of_struct_of_int32 (block, &sub))
2238 NEXT_EXPECTING_TRUE (&sub);
2239 if (!read_array_of_struct_of_int32 (block, &sub))
2242 NEXT_EXPECTING_TRUE (&sub);
2243 if (!read_array_of_struct_of_int32 (block, &sub))
2246 NEXT_EXPECTING_FALSE (&sub);
2252 write_array_of_struct_of_array_of_int32 (DataBlock *block,
2253 DBusTypeWriter *writer)
2255 DataBlockState saved;
2258 data_block_save (block, &saved);
2260 if (!_dbus_type_writer_recurse_array (writer,
2261 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2262 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
2263 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
2264 DBUS_STRUCT_END_CHAR_AS_STRING,
2268 if (!write_struct_of_array_of_int32 (block, &sub))
2270 data_block_restore (block, &saved);
2274 if (!write_struct_of_array_of_int32 (block, &sub))
2276 data_block_restore (block, &saved);
2280 if (!write_struct_of_array_of_int32 (block, &sub))
2282 data_block_restore (block, &saved);
2286 if (!_dbus_type_writer_unrecurse (writer, &sub))
2288 data_block_restore (block, &saved);
2296 read_array_of_struct_of_array_of_int32 (DataBlock *block,
2297 DBusTypeReader *reader)
2301 check_expected_type (reader, DBUS_TYPE_ARRAY);
2303 _dbus_type_reader_recurse (reader, &sub);
2305 check_expected_type (&sub, DBUS_TYPE_STRUCT);
2307 if (!read_struct_of_array_of_int32 (block, &sub))
2310 NEXT_EXPECTING_TRUE (&sub);
2312 if (!read_struct_of_array_of_int32 (block, &sub))
2315 NEXT_EXPECTING_TRUE (&sub);
2317 if (!read_struct_of_array_of_int32 (block, &sub))
2320 NEXT_EXPECTING_FALSE (&sub);
2330 ITEM_STRUCT_OF_INT32,
2331 ITEM_STRUCT_OF_STRUCTS,
2332 ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2334 ITEM_ARRAY_OF_INT32,
2335 ITEM_ARRAY_OF_INT32_EMPTY,
2336 ITEM_ARRAY_OF_ARRAY_OF_INT32,
2337 ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2338 ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2340 ITEM_STRUCT_OF_ARRAY_OF_INT32,
2341 ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2343 ITEM_ARRAY_OF_STRUCT_OF_INT32,
2344 ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2346 ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2347 ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2353 typedef dbus_bool_t (* WriteItemFunc) (DataBlock *block,
2354 DBusTypeWriter *writer);
2355 typedef dbus_bool_t (* ReadItemFunc) (DataBlock *block,
2356 DBusTypeReader *reader);
2362 WriteItemFunc write_item_func;
2363 ReadItemFunc read_item_func;
2366 static CheckMarshalItem items[] = {
2368 ITEM_INT32, write_int32, read_int32 },
2369 { "struct with two int32",
2370 ITEM_STRUCT_OF_INT32, write_struct_of_int32, read_struct_of_int32 },
2371 { "struct with three structs of two int32",
2372 ITEM_STRUCT_OF_STRUCTS, write_struct_of_structs, read_struct_of_structs },
2373 { "struct of two structs of three structs of two int32",
2374 ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2375 write_struct_of_structs_of_structs,
2376 read_struct_of_structs_of_structs },
2378 ITEM_ARRAY_OF_INT32, write_array_of_int32, read_array_of_int32 },
2379 { "empty array of int32",
2380 ITEM_ARRAY_OF_INT32_EMPTY, write_array_of_int32_empty, read_array_of_int32_empty },
2381 { "array of array of int32",
2382 ITEM_ARRAY_OF_ARRAY_OF_INT32,
2383 write_array_of_array_of_int32, read_array_of_array_of_int32 },
2384 { "empty array of array of int32",
2385 ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2386 write_array_of_array_of_int32_empty, read_array_of_array_of_int32_empty },
2387 { "array of array of array of int32",
2388 ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2389 write_array_of_array_of_array_of_int32, read_array_of_array_of_array_of_int32 },
2390 { "struct of array of int32",
2391 ITEM_STRUCT_OF_ARRAY_OF_INT32, write_struct_of_array_of_int32, read_struct_of_array_of_int32 },
2392 { "struct of struct of array of int32",
2393 ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2394 write_struct_of_struct_of_array_of_int32, read_struct_of_struct_of_array_of_int32 },
2395 { "array of struct of int32",
2396 ITEM_ARRAY_OF_STRUCT_OF_INT32, write_array_of_struct_of_int32, read_array_of_struct_of_int32 },
2397 { "array of array of struct of int32",
2398 ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2399 write_array_of_array_of_struct_of_int32, read_array_of_array_of_struct_of_int32 },
2401 { "struct of array of struct of int32",
2402 ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2403 write_struct_of_array_of_struct_of_int32, read_struct_of_array_of_struct_of_int32 },
2404 { "array of struct of array of int32",
2405 ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2406 write_array_of_struct_of_array_of_int32, read_array_of_struct_of_array_of_int32 },
2411 /* Array of items from the above items[]; -1 terminated */
2415 static TestRun runs[] = {
2416 { { ITEM_INVALID } },
2419 { { ITEM_INT32, ITEM_INVALID } },
2420 { { ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2421 { { ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2423 /* STRUCT_OF_INT32 */
2424 { { ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2425 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2426 { { ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2427 { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2428 { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2430 /* STRUCT_OF_STRUCTS */
2431 { { ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2432 { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2433 { { ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2434 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2435 { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2436 { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2438 /* STRUCT_OF_STRUCTS_OF_STRUCTS */
2439 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2440 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2441 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2442 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2443 { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2444 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2446 /* ARRAY_OF_INT32 */
2447 { { ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2448 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2449 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2450 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2451 { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2452 { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2453 { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2454 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2455 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2456 { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2458 /* ARRAY_OF_ARRAY_OF_INT32 */
2459 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2460 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2461 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2462 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2463 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2464 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2465 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2466 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2467 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2468 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2470 /* ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32 */
2471 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2472 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2473 { { 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 } },
2474 { { 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 } },
2475 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2476 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2477 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2478 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2479 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2480 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2482 /* STRUCT_OF_ARRAY_OF_INT32 */
2483 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2484 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2485 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2486 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2487 { { ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2488 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2490 /* STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32 */
2491 { { ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2493 /* ARRAY_OF_STRUCT_OF_INT32 */
2494 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2495 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2496 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2497 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2498 { { ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2499 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2501 /* ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32 */
2502 { { ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2504 /* STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32 */
2505 { { ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2507 /* ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32 */
2508 { { ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2513 perform_one_run (DataBlock *block,
2517 DBusTypeReader reader;
2518 DBusTypeWriter writer;
2520 DataBlockState saved;
2526 _dbus_verbose ("run byteorder %s items ",
2527 byte_order == DBUS_LITTLE_ENDIAN ? "little" : "big");
2529 while (run->items[i] != ITEM_INVALID)
2531 CheckMarshalItem *item = &items[run->items[i]];
2533 _dbus_verbose ("%s ", item->desc);
2536 _dbus_verbose (" = %d items\n", i);
2539 data_block_save (block, &saved);
2541 data_block_init_reader_writer (block,
2546 while (run->items[i] != ITEM_INVALID)
2548 CheckMarshalItem *item = &items[run->items[i]];
2550 _dbus_verbose (">>writing %s\n", item->desc);
2552 if (!(* item->write_item_func) (block, &writer))
2558 while (run->items[i] != ITEM_INVALID)
2560 CheckMarshalItem *item = &items[run->items[i]];
2562 _dbus_verbose (">>data for reading %s\n", item->desc);
2564 _dbus_verbose_bytes_of_string (reader.type_str, 0,
2565 _dbus_string_get_length (reader.type_str));
2566 _dbus_verbose_bytes_of_string (reader.value_str, 0,
2567 _dbus_string_get_length (reader.value_str));
2569 _dbus_verbose (">>reading %s\n", item->desc);
2571 if (!(* item->read_item_func) (block, &reader))
2574 _dbus_type_reader_next (&reader);
2582 data_block_restore (block, &saved);
2587 perform_all_runs (int byte_order,
2596 if (!data_block_init (&block))
2599 if (!_dbus_string_lengthen (&block.signature, initial_offset))
2602 if (!_dbus_string_lengthen (&block.body, initial_offset))
2606 while (i < _DBUS_N_ELEMENTS (runs))
2608 if (!perform_one_run (&block, byte_order, &runs[i]))
2617 data_block_free (&block);
2623 perform_all_items (int byte_order,
2633 if (!data_block_init (&block))
2637 if (!_dbus_string_lengthen (&block.signature, initial_offset))
2640 if (!_dbus_string_lengthen (&block.body, initial_offset))
2643 /* Create a run containing all the items */
2645 while (i < _DBUS_N_ELEMENTS (items))
2647 _dbus_assert (i == items[i].which);
2649 run.items[i] = items[i].which;
2654 run.items[i] = ITEM_INVALID;
2656 if (!perform_one_run (&block, byte_order, &run))
2662 data_block_free (&block);
2668 recursive_marshal_test_iteration (void *data)
2675 if (!perform_all_runs (DBUS_LITTLE_ENDIAN, i))
2677 if (!perform_all_runs (DBUS_BIG_ENDIAN, i))
2679 if (!perform_all_items (DBUS_LITTLE_ENDIAN, i))
2681 if (!perform_all_items (DBUS_BIG_ENDIAN, i))
2690 typedef struct TestTypeNode TestTypeNode;
2691 typedef struct TestTypeNodeClass TestTypeNodeClass;
2692 typedef struct TestTypeNodeContainer TestTypeNodeContainer;
2693 typedef struct TestTypeNodeContainerClass TestTypeNodeContainerClass;
2697 const TestTypeNodeClass *klass;
2700 struct TestTypeNodeContainer
2706 struct TestTypeNodeClass
2712 dbus_bool_t (* construct) (TestTypeNode *node);
2713 void (* destroy) (TestTypeNode *node);
2715 dbus_bool_t (* write_value) (TestTypeNode *node,
2717 DBusTypeWriter *writer,
2719 dbus_bool_t (* read_value) (TestTypeNode *node,
2721 DBusTypeReader *reader,
2723 dbus_bool_t (* build_signature) (TestTypeNode *node,
2727 struct TestTypeNodeContainerClass
2729 TestTypeNodeClass base;
2732 static dbus_bool_t int32_write_value (TestTypeNode *node,
2734 DBusTypeWriter *writer,
2736 static dbus_bool_t int32_read_value (TestTypeNode *node,
2738 DBusTypeReader *reader,
2740 static dbus_bool_t struct_1_write_value (TestTypeNode *node,
2742 DBusTypeWriter *writer,
2744 static dbus_bool_t struct_1_read_value (TestTypeNode *node,
2746 DBusTypeReader *reader,
2748 static dbus_bool_t struct_1_build_signature (TestTypeNode *node,
2750 static dbus_bool_t struct_2_write_value (TestTypeNode *node,
2752 DBusTypeWriter *writer,
2754 static dbus_bool_t struct_2_read_value (TestTypeNode *node,
2756 DBusTypeReader *reader,
2758 static dbus_bool_t struct_2_build_signature (TestTypeNode *node,
2760 static dbus_bool_t array_build_signature (TestTypeNode *node,
2762 static dbus_bool_t array_1_write_value (TestTypeNode *node,
2764 DBusTypeWriter *writer,
2766 static dbus_bool_t array_1_read_value (TestTypeNode *node,
2768 DBusTypeReader *reader,
2770 static dbus_bool_t array_0_write_value (TestTypeNode *node,
2772 DBusTypeWriter *writer,
2774 static dbus_bool_t array_0_read_value (TestTypeNode *node,
2776 DBusTypeReader *reader,
2778 static dbus_bool_t array_2_write_value (TestTypeNode *node,
2780 DBusTypeWriter *writer,
2782 static dbus_bool_t array_2_read_value (TestTypeNode *node,
2784 DBusTypeReader *reader,
2786 static void container_destroy (TestTypeNode *node);
2790 static const TestTypeNodeClass int32_class = {
2792 sizeof (TestTypeNode),
2800 static const TestTypeNodeClass uint32_class = {
2802 sizeof (TestTypeNode),
2805 int32_write_value, /* recycle from int32 */
2806 int32_read_value, /* recycle from int32 */
2810 static const TestTypeNodeClass struct_1_class = {
2812 sizeof (TestTypeNodeContainer),
2815 struct_1_write_value,
2816 struct_1_read_value,
2817 struct_1_build_signature
2820 static const TestTypeNodeClass struct_2_class = {
2822 sizeof (TestTypeNodeContainer),
2825 struct_2_write_value,
2826 struct_2_read_value,
2827 struct_2_build_signature
2830 static const TestTypeNodeClass array_0_class = {
2832 sizeof (TestTypeNodeContainer),
2835 array_0_write_value,
2837 array_build_signature
2840 static const TestTypeNodeClass array_1_class = {
2842 sizeof (TestTypeNodeContainer),
2845 array_1_write_value,
2847 array_build_signature
2850 static const TestTypeNodeClass array_2_class = {
2852 sizeof (TestTypeNodeContainer),
2855 array_2_write_value,
2857 array_build_signature
2860 static const TestTypeNodeClass* const
2865 #define N_BASICS (_DBUS_N_ELEMENTS (basic_nodes))
2867 static const TestTypeNodeClass* const
2868 container_nodes[] = {
2875 #define N_CONTAINERS (_DBUS_N_ELEMENTS (container_nodes))
2877 static TestTypeNode*
2878 node_new (const TestTypeNodeClass *klass)
2882 node = dbus_malloc0 (klass->instance_size);
2886 node->klass = klass;
2888 if (klass->construct)
2890 if (!(* klass->construct) (node))
2901 node_destroy (TestTypeNode *node)
2903 if (node->klass->destroy)
2904 (* node->klass->destroy) (node);
2909 node_write_value (TestTypeNode *node,
2911 DBusTypeWriter *writer,
2914 return (* node->klass->write_value) (node, block, writer, seed);
2918 node_read_value (TestTypeNode *node,
2920 DBusTypeReader *reader,
2923 return (* node->klass->read_value) (node, block, reader, seed);
2927 node_build_signature (TestTypeNode *node,
2930 if (node->klass->build_signature)
2931 return (* node->klass->build_signature) (node, str);
2933 return _dbus_string_append_byte (str, node->klass->typecode);
2937 node_append_child (TestTypeNode *node,
2938 TestTypeNode *child)
2940 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2942 _dbus_assert (node->klass->instance_size >= (int) sizeof (TestTypeNodeContainer));
2944 if (!_dbus_list_append (&container->children, child))
2945 _dbus_assert_not_reached ("no memory"); /* we never check the return value on node_append_child anyhow - it's run from outside the malloc-failure test code */
2952 const DBusString *signature;
2956 TestTypeNode **nodes;
2958 } NodeIterationData;
2961 run_test_nodes_iteration (void *data)
2963 NodeIterationData *nid = data;
2964 DBusTypeReader reader;
2965 DBusTypeWriter writer;
2969 * 1. write the value
2970 * 2. strcmp-compare with the signature we built
2972 * 4. type-iterate the signature and the value and see if they are the same type-wise
2974 data_block_init_reader_writer (nid->block,
2979 while (i < nid->n_nodes)
2981 if (!node_write_value (nid->nodes[i], nid->block, &writer, i))
2987 if (!_dbus_string_equal_substring (nid->signature, 0, _dbus_string_get_length (nid->signature),
2988 &nid->block->signature, nid->type_offset))
2990 _dbus_warn ("Expected signature '%s' and got '%s' with initial offset %d\n",
2991 _dbus_string_get_const_data (nid->signature),
2992 _dbus_string_get_const_data_len (&nid->block->signature, nid->type_offset, 0),
2994 _dbus_assert_not_reached ("wrong signature");
2998 while (i < nid->n_nodes)
3000 if (!node_read_value (nid->nodes[i], nid->block, &reader, i))
3003 if (i + 1 == nid->n_nodes)
3004 NEXT_EXPECTING_FALSE (&reader);
3006 NEXT_EXPECTING_TRUE (&reader);
3011 /* FIXME type-iterate both signature and value */
3017 run_test_nodes_in_one_configuration (TestTypeNode **nodes,
3019 const DBusString *signature,
3024 NodeIterationData nid;
3026 if (!data_block_init (&block))
3027 _dbus_assert_not_reached ("no memory");
3029 if (!_dbus_string_lengthen (&block.signature, initial_offset))
3030 _dbus_assert_not_reached ("no memory");
3032 if (!_dbus_string_lengthen (&block.body, initial_offset))
3033 _dbus_assert_not_reached ("no memory");
3035 nid.signature = signature;
3037 nid.type_offset = initial_offset;
3039 nid.n_nodes = n_nodes;
3040 nid.byte_order = byte_order;
3042 _dbus_test_oom_handling ("running test node",
3043 run_test_nodes_iteration,
3046 data_block_free (&block);
3050 run_test_nodes (TestTypeNode **nodes,
3054 DBusString signature;
3056 if (!_dbus_string_init (&signature))
3057 _dbus_assert_not_reached ("no memory");
3062 if (! node_build_signature (nodes[i], &signature))
3063 _dbus_assert_not_reached ("no memory");
3068 _dbus_verbose (">>> test nodes with signature '%s'\n",
3069 _dbus_string_get_const_data (&signature));
3071 /* We do start offset 0 through 9, to get various alignment cases. Still this
3072 * obviously makes the test suite run 10x as slow.
3077 run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
3078 DBUS_LITTLE_ENDIAN, i);
3079 run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
3080 DBUS_BIG_ENDIAN, i);
3085 _dbus_string_free (&signature);
3088 #define N_VALUES (N_BASICS * N_CONTAINERS + N_BASICS)
3090 static TestTypeNode*
3091 value_generator (int *ip)
3094 const TestTypeNodeClass *child_klass;
3095 const TestTypeNodeClass *container_klass;
3096 TestTypeNode *child;
3099 _dbus_assert (i <= N_VALUES);
3105 else if (i < N_BASICS)
3107 node = node_new (basic_nodes[i]);
3111 /* imagine an array:
3112 * container 0 of basic 0
3113 * container 0 of basic 1
3114 * container 0 of basic 2
3115 * container 1 of basic 0
3116 * container 1 of basic 1
3117 * container 1 of basic 2
3121 container_klass = container_nodes[i / N_BASICS];
3122 child_klass = basic_nodes[i % N_BASICS];
3124 node = node_new (container_klass);
3125 child = node_new (child_klass);
3127 node_append_child (node, child);
3130 *ip += 1; /* increment the generator */
3136 make_and_run_values_inside_container (const TestTypeNodeClass *container_klass,
3140 TestTypeNode *container;
3141 TestTypeNode *child;
3144 root = node_new (container_klass);
3146 for (i = 1; i < n_nested; i++)
3148 child = node_new (container_klass);
3149 node_append_child (container, child);
3153 /* container should now be the most-nested container */
3156 while ((child = value_generator (&i)))
3158 node_append_child (container, child);
3160 run_test_nodes (&root, 1);
3162 _dbus_list_clear (&((TestTypeNodeContainer*)container)->children);
3163 node_destroy (child);
3166 node_destroy (root);
3170 make_and_run_test_nodes (void)
3174 /* We try to do this in order of "complicatedness" so that test
3175 * failures tend to show up in the simplest test case that
3176 * demonstrates the failure. There are also some tests that run
3177 * more than once for this reason, first while going through simple
3178 * cases, second while going through a broader range of complex
3181 /* Each basic node. The basic nodes should include:
3183 * - each fixed-size type (in such a way that it has different values each time,
3184 * so we can tell if we mix two of them up)
3185 * - strings of length 0-9
3189 /* Each container node. The container nodes should include:
3191 * struct with 1 and 2 copies of the contained item
3192 * array with 0, 1, 2 copies of the contained item
3195 /* Let a "value" be a basic node, or a container containing a single basic node.
3196 * Let n_values be the number of such values i.e. (n_container * n_basic + n_basic)
3197 * When iterating through all values to make combinations, do the basic types
3198 * first and the containers second.
3200 /* Each item is shown with its number of iterations to complete so
3201 * we can keep a handle on this unit test
3204 /* FIXME test just an empty body, no types at all */
3206 _dbus_verbose (">>> >>> Each value by itself %d iterations\n",
3211 while ((node = value_generator (&i)))
3213 run_test_nodes (&node, 1);
3215 node_destroy (node);
3219 _dbus_verbose (">>> >>> All values in one big toplevel 1 iteration\n");
3221 TestTypeNode *nodes[N_VALUES];
3224 while ((nodes[i] = value_generator (&i)))
3227 run_test_nodes (nodes, N_VALUES);
3229 for (i = 0; i < N_VALUES; i++)
3230 node_destroy (nodes[i]);
3233 _dbus_verbose (">>> >>> Each value,value pair combination as toplevel, in both orders %d iterations\n",
3234 N_VALUES * N_VALUES * 2);
3236 TestTypeNode *nodes[2];
3239 while ((nodes[0] = value_generator (&i)))
3242 while ((nodes[1] = value_generator (&j)))
3244 run_test_nodes (nodes, 2);
3246 node_destroy (nodes[1]);
3249 node_destroy (nodes[0]);
3253 _dbus_verbose (">>> >>> Each container containing each value %d iterations\n",
3254 N_CONTAINERS * N_VALUES);
3255 for (i = 0; i < N_CONTAINERS; i++)
3257 const TestTypeNodeClass *container_klass = container_nodes[i];
3259 make_and_run_values_inside_container (container_klass, 1);
3262 _dbus_verbose (">>> >>> Each container of same container of each value %d iterations\n",
3263 N_CONTAINERS * N_VALUES);
3264 for (i = 0; i < N_CONTAINERS; i++)
3266 const TestTypeNodeClass *container_klass = container_nodes[i];
3268 make_and_run_values_inside_container (container_klass, 2);
3271 _dbus_verbose (">>> >>> Each container of same container of same container of each value %d iterations\n",
3272 N_CONTAINERS * N_VALUES);
3273 for (i = 0; i < N_CONTAINERS; i++)
3275 const TestTypeNodeClass *container_klass = container_nodes[i];
3277 make_and_run_values_inside_container (container_klass, 3);
3280 _dbus_verbose (">>> >>> Each value,value pair inside a struct %d iterations\n",
3281 N_VALUES * N_VALUES);
3283 TestTypeNode *val1, *val2;
3286 node = node_new (&struct_1_class);
3289 while ((val1 = value_generator (&i)))
3292 while ((val2 = value_generator (&j)))
3294 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3296 node_append_child (node, val1);
3297 node_append_child (node, val2);
3299 run_test_nodes (&node, 1);
3301 _dbus_list_clear (&container->children);
3302 node_destroy (val2);
3304 node_destroy (val1);
3306 node_destroy (node);
3309 _dbus_verbose (">>> >>> all values in one big struct 1 iteration\n");
3312 TestTypeNode *child;
3314 node = node_new (&struct_1_class);
3317 while ((child = value_generator (&i)))
3318 node_append_child (node, child);
3320 run_test_nodes (&node, 1);
3322 node_destroy (node);
3325 _dbus_verbose (">>> >>> Each container of each container of each value %d iterations\n",
3326 N_CONTAINERS * N_CONTAINERS * N_VALUES);
3327 for (i = 0; i < N_CONTAINERS; i++)
3329 const TestTypeNodeClass *outer_container_klass = container_nodes[i];
3330 TestTypeNode *outer_container = node_new (outer_container_klass);
3332 for (j = 0; j < N_CONTAINERS; j++)
3334 TestTypeNode *child;
3335 const TestTypeNodeClass *inner_container_klass = container_nodes[j];
3336 TestTypeNode *inner_container = node_new (inner_container_klass);
3338 node_append_child (outer_container, inner_container);
3341 while ((child = value_generator (&m)))
3343 node_append_child (inner_container, child);
3345 run_test_nodes (&outer_container, 1);
3347 _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
3348 node_destroy (child);
3350 _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
3351 node_destroy (inner_container);
3353 node_destroy (outer_container);
3356 _dbus_verbose (">>> >>> Each container of each container of each container of each value %d iterations\n",
3357 N_CONTAINERS * N_CONTAINERS * N_CONTAINERS * N_VALUES);
3358 for (i = 0; i < N_CONTAINERS; i++)
3360 const TestTypeNodeClass *outer_container_klass = container_nodes[i];
3361 TestTypeNode *outer_container = node_new (outer_container_klass);
3363 for (j = 0; j < N_CONTAINERS; j++)
3365 const TestTypeNodeClass *inner_container_klass = container_nodes[j];
3366 TestTypeNode *inner_container = node_new (inner_container_klass);
3368 node_append_child (outer_container, inner_container);
3370 for (k = 0; k < N_CONTAINERS; k++)
3372 TestTypeNode *child;
3373 const TestTypeNodeClass *center_container_klass = container_nodes[k];
3374 TestTypeNode *center_container = node_new (center_container_klass);
3376 node_append_child (inner_container, center_container);
3379 while ((child = value_generator (&m)))
3381 node_append_child (center_container, child);
3383 run_test_nodes (&outer_container, 1);
3385 _dbus_list_clear (&((TestTypeNodeContainer*)center_container)->children);
3386 node_destroy (child);
3388 _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
3389 node_destroy (center_container);
3391 _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
3392 node_destroy (inner_container);
3394 node_destroy (outer_container);
3397 _dbus_verbose (">>> >>> Each value,value,value triplet combination as toplevel, in all orders %d iterations\n",
3398 N_VALUES * N_VALUES * N_VALUES);
3400 TestTypeNode *nodes[3];
3403 while ((nodes[0] = value_generator (&i)))
3406 while ((nodes[1] = value_generator (&j)))
3409 while ((nodes[2] = value_generator (&k)))
3411 run_test_nodes (nodes, 3);
3413 node_destroy (nodes[2]);
3415 node_destroy (nodes[1]);
3417 node_destroy (nodes[0]);
3422 dbus_bool_t _dbus_marshal_recursive_test (void);
3425 _dbus_marshal_recursive_test (void)
3427 /* The new comprehensive tests */
3430 make_and_run_test_nodes ();
3435 _dbus_test_oom_handling ("recursive marshaling",
3436 recursive_marshal_test_iteration,
3445 main (int argc, char **argv)
3447 _dbus_marshal_recursive_test ();
3457 * Implementations of each type node class
3464 int32_from_seed (int seed)
3466 /* Generate an integer value that's predictable from seed. We could
3467 * just use seed itself, but that would only ever touch one byte of
3468 * the int so would miss some kinds of bug.
3472 v = 42; /* just to quiet compiler afaik */
3479 v = SAMPLE_INT32_ALTERNATE;
3493 v *= seed; /* wraps around eventually, which is fine */
3499 int32_write_value (TestTypeNode *node,
3501 DBusTypeWriter *writer,
3504 /* also used for uint32 */
3507 v = int32_from_seed (seed);
3509 return _dbus_type_writer_write_basic (writer,
3510 node->klass->typecode,
3515 int32_read_value (TestTypeNode *node,
3517 DBusTypeReader *reader,
3520 /* also used for uint32 */
3523 check_expected_type (reader, node->klass->typecode);
3525 _dbus_type_reader_read_basic (reader,
3526 (dbus_int32_t*) &v);
3528 _dbus_assert (v == int32_from_seed (seed));
3534 struct_N_write_value (TestTypeNode *node,
3536 DBusTypeWriter *writer,
3539 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3540 DataBlockState saved;
3544 _dbus_assert (container->children != NULL);
3546 data_block_save (block, &saved);
3548 if (!_dbus_type_writer_recurse_struct (writer,
3553 while (i < n_copies)
3557 link = _dbus_list_get_first_link (&container->children);
3558 while (link != NULL)
3560 TestTypeNode *child = link->data;
3561 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3563 if (!node_write_value (child, block, &sub, i))
3565 data_block_restore (block, &saved);
3575 if (!_dbus_type_writer_unrecurse (writer, &sub))
3577 data_block_restore (block, &saved);
3585 struct_N_read_value (TestTypeNode *node,
3587 DBusTypeReader *reader,
3590 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3594 check_expected_type (reader, DBUS_TYPE_STRUCT);
3596 _dbus_type_reader_recurse (reader, &sub);
3599 while (i < n_copies)
3603 link = _dbus_list_get_first_link (&container->children);
3604 while (link != NULL)
3606 TestTypeNode *child = link->data;
3607 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3609 if (!node_read_value (child, block, &sub, i))
3612 if (i == (n_copies - 1) && next == NULL)
3613 NEXT_EXPECTING_FALSE (&sub);
3615 NEXT_EXPECTING_TRUE (&sub);
3627 struct_N_build_signature (TestTypeNode *node,
3631 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3635 orig_len = _dbus_string_get_length (str);
3637 if (!_dbus_string_append_byte (str, DBUS_STRUCT_BEGIN_CHAR))
3641 while (i < n_copies)
3645 link = _dbus_list_get_first_link (&container->children);
3646 while (link != NULL)
3648 TestTypeNode *child = link->data;
3649 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3651 if (!node_build_signature (child, str))
3660 if (!_dbus_string_append_byte (str, DBUS_STRUCT_END_CHAR))
3666 _dbus_string_set_length (str, orig_len);
3671 struct_1_write_value (TestTypeNode *node,
3673 DBusTypeWriter *writer,
3676 return struct_N_write_value (node, block, writer, 1);
3680 struct_1_read_value (TestTypeNode *node,
3682 DBusTypeReader *reader,
3685 return struct_N_read_value (node, block, reader, 1);
3689 struct_1_build_signature (TestTypeNode *node,
3692 return struct_N_build_signature (node, str, 1);
3697 struct_2_write_value (TestTypeNode *node,
3699 DBusTypeWriter *writer,
3702 return struct_N_write_value (node, block, writer, 2);
3706 struct_2_read_value (TestTypeNode *node,
3708 DBusTypeReader *reader,
3711 return struct_N_read_value (node, block, reader, 2);
3715 struct_2_build_signature (TestTypeNode *node,
3718 return struct_N_build_signature (node, str, 2);
3722 array_N_write_value (TestTypeNode *node,
3724 DBusTypeWriter *writer,
3727 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3728 DataBlockState saved;
3730 DBusString element_signature;
3733 _dbus_assert (container->children != NULL);
3735 data_block_save (block, &saved);
3737 if (!_dbus_string_init (&element_signature))
3740 if (!node_build_signature (_dbus_list_get_first (&container->children),
3741 &element_signature))
3744 if (!_dbus_type_writer_recurse_array (writer,
3745 _dbus_string_get_const_data (&element_signature),
3750 while (i < n_copies)
3754 link = _dbus_list_get_first_link (&container->children);
3755 while (link != NULL)
3757 TestTypeNode *child = link->data;
3758 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3760 if (!node_write_value (child, block, &sub, i))
3769 if (!_dbus_type_writer_unrecurse (writer, &sub))
3775 data_block_restore (block, &saved);
3776 _dbus_string_free (&element_signature);
3781 array_N_read_value (TestTypeNode *node,
3783 DBusTypeReader *reader,
3786 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3790 check_expected_type (reader, DBUS_TYPE_ARRAY);
3794 _dbus_assert (!_dbus_type_reader_array_is_empty (reader));
3796 _dbus_type_reader_recurse (reader, &sub);
3799 while (i < n_copies)
3803 link = _dbus_list_get_first_link (&container->children);
3804 while (link != NULL)
3806 TestTypeNode *child = link->data;
3807 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3809 if (!node_read_value (child, block, &sub, i))
3812 if (i == (n_copies - 1) && next == NULL)
3813 NEXT_EXPECTING_FALSE (&sub);
3815 NEXT_EXPECTING_TRUE (&sub);
3825 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
3832 array_build_signature (TestTypeNode *node,
3835 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3838 orig_len = _dbus_string_get_length (str);
3840 if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
3843 if (!node_build_signature (_dbus_list_get_first (&container->children),
3850 _dbus_string_set_length (str, orig_len);
3855 array_0_write_value (TestTypeNode *node,
3857 DBusTypeWriter *writer,
3860 return array_N_write_value (node, block, writer, 0);
3864 array_0_read_value (TestTypeNode *node,
3866 DBusTypeReader *reader,
3869 return array_N_read_value (node, block, reader, 0);
3874 array_1_write_value (TestTypeNode *node,
3876 DBusTypeWriter *writer,
3879 return array_N_write_value (node, block, writer, 1);
3883 array_1_read_value (TestTypeNode *node,
3885 DBusTypeReader *reader,
3888 return array_N_read_value (node, block, reader, 1);
3892 array_2_write_value (TestTypeNode *node,
3894 DBusTypeWriter *writer,
3897 return array_N_write_value (node, block, writer, 2);
3901 array_2_read_value (TestTypeNode *node,
3903 DBusTypeReader *reader,
3906 return array_N_read_value (node, block, reader, 2);
3910 container_destroy (TestTypeNode *node)
3912 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3915 link = _dbus_list_get_first_link (&container->children);
3916 while (link != NULL)
3918 TestTypeNode *child = link->data;
3919 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3921 node_destroy (child);
3923 _dbus_list_free_link (link);
3929 #endif /* DBUS_BUILD_TESTS */