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
32 struct DBusTypeReaderClass
35 dbus_bool_t types_only; /* only iterates over types, not values */
36 void (* recurse) (DBusTypeReader *sub,
37 DBusTypeReader *parent);
38 int (* get_current_type) (DBusTypeReader *reader);
39 void (* next) (DBusTypeReader *reader,
44 first_type_in_signature (const DBusString *str,
49 t = _dbus_string_get_byte (str, pos);
51 if (t == DBUS_STRUCT_BEGIN_CHAR)
52 return DBUS_TYPE_STRUCT;
58 element_type_get_alignment (const DBusString *str,
61 return _dbus_type_get_alignment (first_type_in_signature (str, pos));
65 reader_init (DBusTypeReader *reader,
67 const DBusString *type_str,
69 const DBusString *value_str,
72 reader->byte_order = byte_order;
73 reader->finished = FALSE;
74 reader->type_str = type_str;
75 reader->type_pos = type_pos;
76 reader->value_str = value_str;
77 reader->value_pos = value_pos;
81 base_reader_recurse (DBusTypeReader *sub,
82 DBusTypeReader *parent)
84 /* point subreader at the same place as parent */
94 struct_types_only_reader_recurse (DBusTypeReader *sub,
95 DBusTypeReader *parent)
97 base_reader_recurse (sub, parent);
99 _dbus_assert (_dbus_string_get_byte (sub->type_str,
100 sub->type_pos) == DBUS_STRUCT_BEGIN_CHAR);
106 struct_reader_recurse (DBusTypeReader *sub,
107 DBusTypeReader *parent)
109 struct_types_only_reader_recurse (sub, parent);
111 /* struct has 8 byte alignment */
112 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
116 array_types_only_reader_recurse (DBusTypeReader *sub,
117 DBusTypeReader *parent)
119 base_reader_recurse (sub, parent);
121 /* point type_pos at the array element type */
124 sub->u.array.element_type = first_type_in_signature (sub->type_str,
127 /* Init with values likely to crash things if misused */
128 sub->u.array.start_pos = _DBUS_INT_MAX;
129 sub->u.array.len = _DBUS_INT_MAX;
133 array_reader_recurse (DBusTypeReader *sub,
134 DBusTypeReader *parent)
136 dbus_uint32_t array_len;
139 _dbus_assert (!_dbus_type_reader_array_is_empty (parent));
141 array_types_only_reader_recurse (sub, parent);
143 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
145 _dbus_demarshal_basic_type (sub->value_str,
151 sub->u.array.len = array_len;
153 alignment = element_type_get_alignment (sub->type_str,
156 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
158 sub->u.array.start_pos = sub->value_pos;
160 _dbus_verbose (" type reader %p array start = %d array len = %d array element type = %s\n",
162 sub->u.array.start_pos,
164 _dbus_type_to_string (sub->u.array.element_type));
168 variant_reader_recurse (DBusTypeReader *sub,
169 DBusTypeReader *parent)
173 _dbus_assert (!_dbus_type_reader_array_is_empty (parent));
175 base_reader_recurse (sub, parent);
177 /* Variant is 1 byte sig length (without nul), signature with nul,
178 * padding to 8-boundary, then values
181 sig_len = _dbus_string_get_byte (sub->value_str, sub->value_pos);
183 sub->type_str = sub->value_str;
184 sub->type_pos = sub->value_pos + 1;
186 sub->value_pos = sub->type_pos + sig_len + 1;
188 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
190 _dbus_verbose (" type reader %p variant containing '%s'\n",
192 _dbus_string_get_const_data_len (sub->type_str,
197 base_reader_get_current_type (DBusTypeReader *reader)
201 t = first_type_in_signature (reader->type_str,
208 struct_reader_get_current_type (DBusTypeReader *reader)
212 if (reader->finished)
213 t = DBUS_TYPE_INVALID;
215 t = first_type_in_signature (reader->type_str,
222 array_types_only_reader_get_current_type (DBusTypeReader *reader)
226 if (reader->finished)
227 t = DBUS_TYPE_INVALID;
229 t = reader->u.array.element_type;
235 array_reader_get_current_type (DBusTypeReader *reader)
240 /* return the array element type if elements remain, and
241 * TYPE_INVALID otherwise
244 end_pos = reader->u.array.start_pos + reader->u.array.len;
246 _dbus_assert (reader->value_pos <= end_pos);
247 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
249 if (reader->value_pos < end_pos)
250 t = reader->u.array.element_type;
252 t = DBUS_TYPE_INVALID;
258 skip_one_complete_type (const DBusString *type_str,
261 while (_dbus_string_get_byte (type_str, *type_pos) == DBUS_TYPE_ARRAY)
264 if (_dbus_string_get_byte (type_str, *type_pos) == DBUS_STRUCT_BEGIN_CHAR)
271 switch (_dbus_string_get_byte (type_str, *type_pos))
273 case DBUS_STRUCT_BEGIN_CHAR:
276 case DBUS_STRUCT_END_CHAR:
279 case DBUS_TYPE_INVALID:
280 _dbus_assert_not_reached ("unbalanced parens in signature");
291 skip_array_values (int element_type,
292 const DBusString *value_str,
296 dbus_uint32_t array_len;
300 pos = _DBUS_ALIGN_VALUE (*value_pos, 4);
302 _dbus_demarshal_basic_type (value_str,
308 alignment = _dbus_type_get_alignment (element_type);
310 pos = _DBUS_ALIGN_VALUE (pos, alignment);
312 *value_pos = pos + array_len;
316 base_reader_next (DBusTypeReader *reader,
319 switch (current_type)
321 case DBUS_TYPE_STRUCT:
322 /* Scan forward over the entire container contents */
326 /* Recurse into the struct */
327 _dbus_type_reader_recurse (reader, &sub);
329 /* Skip everything in this subreader */
330 while (_dbus_type_reader_next (&sub))
335 /* Now we are at the end of this container */
336 reader->type_pos = sub.type_pos;
338 if (!reader->klass->types_only)
339 reader->value_pos = sub.value_pos;
343 case DBUS_TYPE_ARRAY:
345 if (!reader->klass->types_only)
346 skip_array_values (first_type_in_signature (reader->type_str,
347 reader->type_pos + 1),
348 reader->value_str, &reader->value_pos, reader->byte_order);
350 skip_one_complete_type (reader->type_str, &reader->type_pos);
355 if (!reader->klass->types_only)
356 _dbus_marshal_skip_basic_type (reader->value_str,
357 current_type, reader->byte_order,
360 reader->type_pos += 1;
366 struct_reader_next (DBusTypeReader *reader,
371 base_reader_next (reader, current_type);
373 /* for STRUCT containers we return FALSE at the end of the struct,
374 * for INVALID we return FALSE at the end of the signature.
375 * In both cases we arrange for get_current_type() to return INVALID
376 * which is defined to happen iff we're at the end (no more next())
378 t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
379 if (t == DBUS_STRUCT_END_CHAR)
381 reader->type_pos += 1;
382 reader->finished = TRUE;
387 array_types_only_reader_next (DBusTypeReader *reader,
390 /* We have one "element" to be iterated over
391 * in each array, which is its element type.
392 * So the finished flag indicates whether we've
393 * iterated over it yet or not.
395 reader->finished = TRUE;
399 array_reader_next (DBusTypeReader *reader,
402 /* Skip one array element */
405 end_pos = reader->u.array.start_pos + reader->u.array.len;
407 _dbus_assert (reader->value_pos < end_pos);
408 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
410 if (reader->u.array.element_type == DBUS_TYPE_STRUCT)
414 /* Recurse into the struct */
415 _dbus_type_reader_recurse (reader, &sub);
417 /* Skip everything in this element */
418 while (_dbus_type_reader_next (&sub))
423 /* Now we are at the end of this element */
424 reader->value_pos = sub.value_pos;
426 else if (reader->u.array.element_type == DBUS_TYPE_ARRAY)
428 skip_array_values (first_type_in_signature (reader->type_str,
429 reader->type_pos + 1),
430 reader->value_str, &reader->value_pos, reader->byte_order);
434 _dbus_marshal_skip_basic_type (reader->value_str,
435 current_type, reader->byte_order,
439 _dbus_assert (reader->value_pos <= end_pos);
441 if (reader->value_pos == end_pos)
443 skip_one_complete_type (reader->type_str,
448 static const DBusTypeReaderClass body_reader_class = {
451 NULL, /* body is always toplevel, so doesn't get recursed into */
452 base_reader_get_current_type,
456 static const DBusTypeReaderClass body_types_only_reader_class = {
459 NULL, /* body is always toplevel, so doesn't get recursed into */
460 base_reader_get_current_type,
464 static const DBusTypeReaderClass struct_reader_class = {
467 struct_reader_recurse,
468 struct_reader_get_current_type,
472 static const DBusTypeReaderClass struct_types_only_reader_class = {
475 struct_types_only_reader_recurse,
476 struct_reader_get_current_type,
480 static const DBusTypeReaderClass array_reader_class = {
483 array_reader_recurse,
484 array_reader_get_current_type,
488 static const DBusTypeReaderClass array_types_only_reader_class = {
491 array_types_only_reader_recurse,
492 array_types_only_reader_get_current_type,
493 array_types_only_reader_next
496 static const DBusTypeReaderClass variant_reader_class = {
499 variant_reader_recurse,
500 base_reader_get_current_type,
505 _dbus_type_reader_init (DBusTypeReader *reader,
507 const DBusString *type_str,
509 const DBusString *value_str,
512 reader->klass = &body_reader_class;
514 reader_init (reader, byte_order, type_str, type_pos,
515 value_str, value_pos);
517 _dbus_verbose (" type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
518 reader, reader->type_pos, reader->value_pos,
519 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
523 _dbus_type_reader_init_types_only (DBusTypeReader *reader,
524 const DBusString *type_str,
527 reader->klass = &body_types_only_reader_class;
529 reader_init (reader, DBUS_COMPILER_BYTE_ORDER /* irrelevant */,
530 type_str, type_pos, NULL, _DBUS_INT_MAX /* crashes if we screw up */);
532 _dbus_verbose (" type reader %p init types only type_pos = %d remaining sig '%s'\n",
533 reader, reader->type_pos,
534 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
538 _dbus_type_reader_get_current_type (DBusTypeReader *reader)
542 t = (* reader->klass->get_current_type) (reader);
544 _dbus_assert (t != DBUS_STRUCT_END_CHAR);
545 _dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR);
548 _dbus_verbose (" type reader %p current type_pos = %d type = %s\n",
549 reader, reader->type_pos,
550 _dbus_type_to_string (t));
557 _dbus_type_reader_array_is_empty (DBusTypeReader *reader)
559 dbus_uint32_t array_len;
562 _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY);
563 _dbus_assert (!reader->klass->types_only);
565 len_pos = _DBUS_ALIGN_VALUE (reader->value_pos, 4);
567 _dbus_demarshal_basic_type (reader->value_str,
573 return array_len == 0;
577 _dbus_type_reader_read_basic (DBusTypeReader *reader,
583 _dbus_assert (!reader->klass->types_only);
585 t = _dbus_type_reader_get_current_type (reader);
587 next = reader->value_pos;
588 _dbus_demarshal_basic_type (reader->value_str,
594 _dbus_verbose (" type reader %p read basic type_pos = %d value_pos = %d next = %d remaining sig '%s'\n",
595 reader, reader->type_pos, reader->value_pos, next,
596 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
600 _dbus_type_reader_read_array_of_basic (DBusTypeReader *reader,
605 _dbus_assert (!reader->klass->types_only);
610 * Initialize a new reader pointing to the first type and
611 * corresponding value that's a child of the current container. It's
612 * an error to call this if the current type is a non-container.
614 * Note that DBusTypeReader traverses values, not types. So if you
615 * have an empty array of array of int, you can't recurse into it. You
616 * can only recurse into each element.
618 * @param reader the reader
619 * @param sub a reader to init pointing to the first child
622 _dbus_type_reader_recurse (DBusTypeReader *reader,
627 t = first_type_in_signature (reader->type_str, reader->type_pos);
631 case DBUS_TYPE_STRUCT:
632 if (reader->klass->types_only)
633 sub->klass = &struct_types_only_reader_class;
635 sub->klass = &struct_reader_class;
637 case DBUS_TYPE_ARRAY:
638 if (reader->klass->types_only)
639 sub->klass = &array_types_only_reader_class;
641 sub->klass = &array_reader_class;
643 case DBUS_TYPE_VARIANT:
644 if (reader->klass->types_only)
645 _dbus_assert_not_reached ("can't recurse into variant typecode");
647 sub->klass = &variant_reader_class;
650 _dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t));
651 #ifndef DBUS_DISABLE_CHECKS
652 if (t == DBUS_TYPE_INVALID)
653 _dbus_warn ("You can't recurse into an empty array or off the end of a message body\n");
654 #endif /* DBUS_DISABLE_CHECKS */
656 _dbus_assert_not_reached ("don't yet handle recursing into this type");
659 (* sub->klass->recurse) (sub, reader);
661 _dbus_verbose (" type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
662 sub, sub->type_pos, sub->value_pos,
663 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
667 * Skip to the next value on this "level". e.g. the next field in a
668 * struct, the next value in an array, the next key or value in a
669 * dict. Returns FALSE at the end of the current container.
671 * @param reader the reader
672 * @returns FALSE if nothing more to read at or below this level
675 _dbus_type_reader_next (DBusTypeReader *reader)
679 t = _dbus_type_reader_get_current_type (reader);
681 _dbus_verbose (" type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
682 reader, reader->type_pos, reader->value_pos,
683 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
684 _dbus_type_to_string (t));
686 if (t == DBUS_TYPE_INVALID)
689 (* reader->klass->next) (reader, t);
691 _dbus_verbose (" type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
692 reader, reader->type_pos, reader->value_pos,
693 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
694 _dbus_type_to_string (_dbus_type_reader_get_current_type (reader)));
696 return _dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID;
710 _dbus_type_writer_init (DBusTypeWriter *writer,
712 DBusString *type_str,
714 DBusString *value_str,
717 writer->byte_order = byte_order;
718 writer->type_str = type_str;
719 writer->type_pos = type_pos;
720 writer->value_str = value_str;
721 writer->value_pos = value_pos;
722 writer->container_type = DBUS_TYPE_INVALID;
723 writer->type_pos_is_expectation = FALSE;
725 _dbus_verbose ("writer %p init remaining sig '%s'\n", writer,
726 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
730 _dbus_type_writer_write_basic_no_typecode (DBusTypeWriter *writer,
737 old_value_len = _dbus_string_get_length (writer->value_str);
739 if (!_dbus_marshal_basic_type (writer->value_str,
746 bytes_written = _dbus_string_get_length (writer->value_str) - old_value_len;
748 writer->value_pos += bytes_written;
753 /* If our parent is an array, things are a little bit complicated.
755 * The parent must have a complete element type, such as
756 * "i" or "aai" or "(ii)" or "a(ii)". There can't be
757 * unclosed parens, or an "a" with no following type.
759 * To recurse, the only allowed operation is to recurse into the
760 * first type in the element type. So for "i" you can't recurse, for
761 * "ai" you can recurse into the array, for "(ii)" you can recurse
764 * If you recurse into the array for "ai", then you must specify
765 * "i" for the element type of the array you recurse into.
767 * While inside an array at any level, we need to avoid writing to
768 * type_str, since the type only appears once for the whole array,
769 * it does not appear for each array element.
771 * While inside an array type_pos points to the expected next
772 * typecode, rather than the next place we could write a typecode.
775 writer_recurse_init_and_check (DBusTypeWriter *writer,
779 _dbus_type_writer_init (sub,
786 sub->container_type = container_type;
788 if (writer->type_pos_is_expectation ||
789 (sub->container_type == DBUS_TYPE_ARRAY || sub->container_type == DBUS_TYPE_VARIANT))
790 sub->type_pos_is_expectation = TRUE;
792 sub->type_pos_is_expectation = FALSE;
794 #ifndef DBUS_DISABLE_CHECKS
795 if (writer->type_pos_is_expectation)
799 expected = first_type_in_signature (writer->type_str, writer->type_pos);
801 if (expected != sub->container_type)
803 _dbus_warn ("Writing an element of type %s, but the expected type here is %s\n",
804 _dbus_type_to_string (sub->container_type),
805 _dbus_type_to_string (expected));
806 _dbus_assert_not_reached ("bad array element or variant content written");
809 #endif /* DBUS_DISABLE_CHECKS */
811 _dbus_verbose (" type writer %p recurse parent type_pos = %d value_pos = %d is_expectation = %d container_type = %s remaining sig '%s'\n",
812 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
813 _dbus_type_to_string (writer->container_type),
814 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
815 _dbus_verbose (" type writer %p recurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
816 sub, sub->type_pos, sub->value_pos,
817 sub->type_pos_is_expectation,
818 _dbus_type_to_string (sub->container_type));
822 write_or_verify_typecode (DBusTypeWriter *writer,
825 /* A subwriter inside an array or variant will have type_pos
826 * pointing to the expected typecode; a writer not inside an array
827 * or variant has type_pos pointing to the next place to insert a
830 _dbus_verbose (" type writer %p write_or_verify start type_pos = %d remaining sig '%s'\n",
831 writer, writer->type_pos,
832 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
834 if (writer->type_pos_is_expectation)
836 #ifndef DBUS_DISABLE_CHECKS
840 expected = _dbus_string_get_byte (writer->type_str, writer->type_pos);
842 if (expected != typecode)
844 _dbus_warn ("Array or Variant type requires that type %s be written, but %s was written\n",
845 _dbus_type_to_string (expected), _dbus_type_to_string (typecode));
846 _dbus_assert_not_reached ("bad type inserted somewhere inside an array or variant");
849 #endif /* DBUS_DISABLE_CHECKS */
851 /* if immediately inside an array we'd always be appending an element,
852 * so the expected type doesn't change; if inside a struct or something
853 * below an array, we need to move through said struct or something.
855 if (writer->container_type != DBUS_TYPE_ARRAY)
856 writer->type_pos += 1;
860 if (!_dbus_string_insert_byte (writer->type_str,
865 writer->type_pos += 1;
868 _dbus_verbose (" type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
869 writer, writer->type_pos,
870 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
876 _dbus_type_writer_recurse_struct (DBusTypeWriter *writer,
879 writer_recurse_init_and_check (writer, DBUS_TYPE_STRUCT, sub);
881 /* Ensure that we'll be able to add alignment padding and the typecode */
882 if (!_dbus_string_alloc_space (sub->value_str, 8))
885 if (!_dbus_string_alloc_space (sub->type_str, 1))
888 if (!write_or_verify_typecode (sub, DBUS_STRUCT_BEGIN_CHAR))
889 _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
891 if (!_dbus_string_insert_bytes (sub->value_str,
893 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
895 _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
896 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
902 _dbus_type_writer_recurse_array (DBusTypeWriter *writer,
903 const char *element_type,
906 int element_type_len;
907 DBusString element_type_str;
908 dbus_uint32_t value = 0;
913 writer_recurse_init_and_check (writer, DBUS_TYPE_ARRAY, sub);
915 _dbus_string_init_const (&element_type_str, element_type);
916 element_type_len = _dbus_string_get_length (&element_type_str);
918 #ifndef DBUS_DISABLE_CHECKS
919 if (writer->container_type == DBUS_TYPE_ARRAY)
921 if (!_dbus_string_equal_substring (&element_type_str, 0, element_type_len,
922 writer->type_str, writer->u.array.element_type_pos + 1))
924 _dbus_warn ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
926 _dbus_assert_not_reached ("incompatible type for child array");
929 #endif /* DBUS_DISABLE_CHECKS */
931 /* 4 bytes for the array length and 4 bytes possible padding */
932 if (!_dbus_string_alloc_space (sub->value_str, 8))
935 sub->type_pos += 1; /* move to point to the element type, since type_pos
936 * should be the expected type for further writes
938 sub->u.array.element_type_pos = sub->type_pos;
940 if (!writer->type_pos_is_expectation)
942 /* sub is a toplevel/outermost array so we need to write the type data */
944 /* alloc space for array typecode, element signature, possible 7
947 if (!_dbus_string_alloc_space (writer->type_str, 1 + element_type_len + 7))
950 if (!_dbus_string_insert_byte (writer->type_str,
953 _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
955 if (!_dbus_string_copy (&element_type_str, 0,
956 sub->type_str, sub->u.array.element_type_pos))
957 _dbus_assert_not_reached ("should not have failed to insert array element typecodes");
960 /* If the parent is an array, we hold type_pos pointing at the array element type;
961 * otherwise advance it to reflect the array value we just recursed into
963 if (writer->container_type != DBUS_TYPE_ARRAY)
964 writer->type_pos += 1 + element_type_len;
966 _dbus_assert (writer->type_pos_is_expectation); /* because it's an array */
968 /* Write the length */
969 sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
971 if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
973 _dbus_assert_not_reached ("should not have failed to insert array len");
975 _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
977 /* Write alignment padding for array elements */
978 _dbus_string_init_const (&str, element_type);
979 alignment = element_type_get_alignment (&str, 0);
981 aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
982 if (aligned != sub->value_pos)
984 if (!_dbus_string_insert_bytes (sub->value_str,
986 aligned - sub->value_pos,
988 _dbus_assert_not_reached ("should not have failed to insert alignment padding");
990 sub->value_pos = aligned;
992 sub->u.array.start_pos = sub->value_pos;
994 _dbus_assert (sub->u.array.start_pos == sub->value_pos);
995 _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
997 _dbus_verbose (" type writer %p recurse array done remaining sig '%s'\n", sub,
998 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
1003 /* Variant value will normally have:
1004 * 1 byte signature length not including nul
1005 * signature typecodes (nul terminated)
1006 * padding to 8-boundary
1007 * body according to signature
1009 * The signature string can only have a single type
1010 * in it but that type may be complex/recursive.
1012 * So a typical variant type with the integer 3 will have these
1014 * 0x1 'i' '\0' [padding to 8-boundary] 0x0 0x0 0x0 0x3
1016 * For an array of 4-byte types stuffed into variants, the padding to
1017 * 8-boundary is only the 1 byte that is required for the 4-boundary
1018 * anyhow for all array elements after the first one. And for single
1019 * variants in isolation, wasting a few bytes is hardly a big deal.
1021 * The main world of hurt for writing out a variant is that the type
1022 * string is the same string as the value string. Which means
1023 * inserting to the type string will move the value_pos; and it means
1024 * that inserting to the type string could break type alignment.
1026 * This type alignment issue is why the body of the variant is always
1027 * 8-aligned. Then we know that re-8-aligning the start of the body
1028 * will always correctly align the full contents of the variant type.
1031 _dbus_type_writer_recurse_variant (DBusTypeWriter *writer,
1032 const char *contained_type,
1033 DBusTypeWriter *sub)
1035 int contained_type_len;
1036 DBusString contained_type_str;
1038 writer_recurse_init_and_check (writer, DBUS_TYPE_VARIANT, sub);
1040 _dbus_string_init_const (&contained_type_str, contained_type);
1042 contained_type_len = _dbus_string_get_length (&contained_type_str);
1044 /* Allocate space for the worst case, which is 1 byte sig
1045 * length, nul byte at end of sig, and 7 bytes padding to
1048 if (!_dbus_string_alloc_space (sub->value_str, contained_type_len + 9))
1051 /* write VARIANT typecode to the parent's type string */
1052 if (!write_or_verify_typecode (sub, DBUS_TYPE_VARIANT))
1055 if (!_dbus_string_insert_byte (sub->value_str,
1057 contained_type_len))
1058 _dbus_assert_not_reached ("should not have failed to insert variant type sig len");
1060 sub->value_pos += 1;
1062 /* Here we switch over to the expected type sig we're about to write */
1063 sub->type_str = sub->value_str;
1064 sub->type_pos = sub->value_pos;
1066 if (!_dbus_string_copy (&contained_type_str, 0,
1067 sub->value_str, sub->value_pos))
1068 _dbus_assert_not_reached ("should not have failed to insert variant type sig");
1070 sub->value_pos += contained_type_len;
1072 if (!_dbus_string_insert_byte (sub->value_str,
1075 _dbus_assert_not_reached ("should not have failed to insert variant type nul termination");
1077 sub->value_pos += 1;
1079 if (!_dbus_string_insert_bytes (sub->value_str,
1081 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
1083 _dbus_assert_not_reached ("should not have failed to insert alignment padding for variant body");
1084 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
1090 _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
1091 DBusTypeWriter *sub)
1093 _dbus_assert (sub->type_pos > 0); /* can't be recursed if this fails */
1095 /* type_pos_is_expectation never gets unset once set, or we'd get all hosed */
1096 _dbus_assert (!writer->type_pos_is_expectation ||
1097 (writer->type_pos_is_expectation && sub->type_pos_is_expectation));
1099 _dbus_verbose (" type writer %p unrecurse type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
1100 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
1101 _dbus_type_to_string (writer->container_type));
1102 _dbus_verbose (" type writer %p unrecurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
1103 sub, sub->type_pos, sub->value_pos,
1104 sub->type_pos_is_expectation,
1105 _dbus_type_to_string (sub->container_type));
1107 if (sub->container_type == DBUS_TYPE_STRUCT)
1109 if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
1112 else if (sub->container_type == DBUS_TYPE_ARRAY)
1116 /* Set the array length */
1117 len = sub->value_pos - sub->u.array.start_pos;
1118 _dbus_marshal_set_uint32 (sub->value_str,
1120 sub->u.array.len_pos,
1122 _dbus_verbose (" filled in sub array len to %u at len_pos %d\n",
1123 len, sub->u.array.len_pos);
1126 /* Now get type_pos right for the parent writer. Here are the cases:
1128 * Cases !writer->type_pos_is_expectation:
1129 * (in these cases we want to update to the new insertion point)
1131 * - if we recursed into a STRUCT then we didn't know in advance
1132 * what the types in the struct would be; so we have to fill in
1133 * that information now.
1134 * writer->type_pos = sub->type_pos
1136 * - if we recursed into anything else, we knew the full array
1137 * type, or knew the single typecode marking VARIANT, so
1138 * writer->type_pos is already correct.
1139 * writer->type_pos should remain as-is
1141 * - note that the parent is never an ARRAY or VARIANT, if it were
1142 * then type_pos_is_expectation would be TRUE. The parent
1143 * is thus known to be a toplevel or STRUCT.
1145 * Cases where writer->type_pos_is_expectation:
1146 * (in these cases we want to update to next expected type to write)
1148 * - we recursed from STRUCT into STRUCT and we didn't increment
1149 * type_pos in the parent just to stay consistent with the
1150 * !writer->type_pos_is_expectation case (though we could
1151 * special-case this in recurse_struct instead if we wanted)
1152 * writer->type_pos = sub->type_pos
1154 * - we recursed from STRUCT into ARRAY or VARIANT and type_pos
1155 * for parent should have been incremented already
1156 * writer->type_pos should remain as-is
1158 * - we recursed from ARRAY into a sub-element, so type_pos in the
1159 * parent is the element type and should remain the element type
1160 * for the benefit of the next child element
1161 * writer->type_pos should remain as-is
1163 * - we recursed from VARIANT into its value, so type_pos in the
1164 * parent makes no difference since there's only one value
1165 * and we just finished writing it and won't use type_pos again
1166 * writer->type_pos should remain as-is
1168 if (sub->container_type == DBUS_TYPE_STRUCT &&
1169 (writer->container_type == DBUS_TYPE_STRUCT ||
1170 writer->container_type == DBUS_TYPE_INVALID))
1172 /* Advance the parent to the next struct field */
1173 writer->type_pos = sub->type_pos;
1176 writer->value_pos = sub->value_pos;
1178 _dbus_verbose (" type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
1179 writer, writer->type_pos, writer->value_pos,
1180 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
1186 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
1192 /* First ensure that our type realloc will succeed */
1193 if (!_dbus_string_alloc_space (writer->type_str, 1))
1198 if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
1201 if (!write_or_verify_typecode (writer, type))
1202 _dbus_assert_not_reached ("failed to write typecode after prealloc");
1207 _dbus_verbose (" type writer %p basic type_pos = %d value_pos = %d is_expectation = %d\n",
1208 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation);
1214 _dbus_type_writer_write_array (DBusTypeWriter *writer,
1223 /** @} */ /* end of DBusMarshal group */
1225 #ifdef DBUS_BUILD_TESTS
1226 #include "dbus-test.h"
1227 #include "dbus-list.h"
1233 DBusString signature;
1244 data_block_init (DataBlock *block)
1246 if (!_dbus_string_init (&block->signature))
1249 if (!_dbus_string_init (&block->body))
1251 _dbus_string_free (&block->signature);
1259 data_block_free (DataBlock *block)
1261 _dbus_string_free (&block->signature);
1262 _dbus_string_free (&block->body);
1266 data_block_save (DataBlock *block,
1267 DataBlockState *state)
1269 state->saved_sig_len = _dbus_string_get_length (&block->signature);
1270 state->saved_body_len = _dbus_string_get_length (&block->body);
1274 data_block_restore (DataBlock *block,
1275 DataBlockState *state)
1277 /* These set_length should be shortening things so should always work */
1279 if (!_dbus_string_set_length (&block->signature,
1280 state->saved_sig_len))
1281 _dbus_assert_not_reached ("could not restore signature length");
1283 if (!_dbus_string_set_length (&block->body,
1284 state->saved_body_len))
1285 _dbus_assert_not_reached ("could not restore body length");
1289 data_block_init_reader_writer (DataBlock *block,
1291 DBusTypeReader *reader,
1292 DBusTypeWriter *writer)
1294 _dbus_type_reader_init (reader,
1297 _dbus_string_get_length (&block->signature),
1299 _dbus_string_get_length (&block->body));
1301 _dbus_type_writer_init (writer,
1304 _dbus_string_get_length (&block->signature),
1306 _dbus_string_get_length (&block->body));
1310 real_check_expected_type (DBusTypeReader *reader,
1312 const char *funcname,
1317 t = _dbus_type_reader_get_current_type (reader);
1321 _dbus_warn ("Read type %s while expecting %s at %s line %d\n",
1322 _dbus_type_to_string (t),
1323 _dbus_type_to_string (expected),
1330 #define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__)
1332 #define NEXT_EXPECTING_TRUE(reader) do { if (!_dbus_type_reader_next (reader)) \
1334 _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d\n", \
1335 _DBUS_FUNCTION_NAME, __LINE__); \
1336 _dbus_assert_not_reached ("test failed"); \
1340 #define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader)) \
1342 _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d\n", \
1343 _DBUS_FUNCTION_NAME, __LINE__); \
1344 _dbus_assert_not_reached ("test failed"); \
1346 check_expected_type (reader, DBUS_TYPE_INVALID); \
1349 #define SAMPLE_INT32 12345678
1350 #define SAMPLE_INT32_ALTERNATE 53781429
1352 write_int32 (DataBlock *block,
1353 DBusTypeWriter *writer)
1355 dbus_int32_t v = SAMPLE_INT32;
1357 return _dbus_type_writer_write_basic (writer,
1363 read_int32 (DataBlock *block,
1364 DBusTypeReader *reader)
1368 check_expected_type (reader, DBUS_TYPE_INT32);
1370 _dbus_type_reader_read_basic (reader,
1371 (dbus_int32_t*) &v);
1373 _dbus_assert (v == SAMPLE_INT32);
1379 write_struct_of_int32 (DataBlock *block,
1380 DBusTypeWriter *writer)
1383 DataBlockState saved;
1386 data_block_save (block, &saved);
1388 if (!_dbus_type_writer_recurse_struct (writer,
1393 if (!_dbus_type_writer_write_basic (&sub,
1397 data_block_restore (block, &saved);
1401 v = SAMPLE_INT32_ALTERNATE;
1402 if (!_dbus_type_writer_write_basic (&sub,
1406 data_block_restore (block, &saved);
1410 if (!_dbus_type_writer_unrecurse (writer, &sub))
1412 data_block_restore (block, &saved);
1420 read_struct_of_int32 (DataBlock *block,
1421 DBusTypeReader *reader)
1426 check_expected_type (reader, DBUS_TYPE_STRUCT);
1428 _dbus_type_reader_recurse (reader, &sub);
1430 check_expected_type (&sub, DBUS_TYPE_INT32);
1432 _dbus_type_reader_read_basic (&sub,
1433 (dbus_int32_t*) &v);
1435 _dbus_assert (v == SAMPLE_INT32);
1437 NEXT_EXPECTING_TRUE (&sub);
1438 check_expected_type (&sub, DBUS_TYPE_INT32);
1440 _dbus_type_reader_read_basic (&sub,
1441 (dbus_int32_t*) &v);
1443 _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1445 NEXT_EXPECTING_FALSE (&sub);
1451 write_struct_of_structs (DataBlock *block,
1452 DBusTypeWriter *writer)
1454 DataBlockState saved;
1457 data_block_save (block, &saved);
1459 if (!_dbus_type_writer_recurse_struct (writer,
1463 if (!write_struct_of_int32 (block, &sub))
1465 data_block_restore (block, &saved);
1468 if (!write_struct_of_int32 (block, &sub))
1470 data_block_restore (block, &saved);
1473 if (!write_struct_of_int32 (block, &sub))
1475 data_block_restore (block, &saved);
1479 if (!_dbus_type_writer_unrecurse (writer, &sub))
1481 data_block_restore (block, &saved);
1489 read_struct_of_structs (DataBlock *block,
1490 DBusTypeReader *reader)
1494 check_expected_type (reader, DBUS_TYPE_STRUCT);
1496 _dbus_type_reader_recurse (reader, &sub);
1498 if (!read_struct_of_int32 (block, &sub))
1501 NEXT_EXPECTING_TRUE (&sub);
1502 if (!read_struct_of_int32 (block, &sub))
1505 NEXT_EXPECTING_TRUE (&sub);
1506 if (!read_struct_of_int32 (block, &sub))
1509 NEXT_EXPECTING_FALSE (&sub);
1515 write_struct_of_structs_of_structs (DataBlock *block,
1516 DBusTypeWriter *writer)
1518 DataBlockState saved;
1521 data_block_save (block, &saved);
1523 if (!_dbus_type_writer_recurse_struct (writer,
1527 if (!write_struct_of_structs (block, &sub))
1529 data_block_restore (block, &saved);
1532 if (!write_struct_of_structs (block, &sub))
1534 data_block_restore (block, &saved);
1538 if (!_dbus_type_writer_unrecurse (writer, &sub))
1540 data_block_restore (block, &saved);
1548 read_struct_of_structs_of_structs (DataBlock *block,
1549 DBusTypeReader *reader)
1553 check_expected_type (reader, DBUS_TYPE_STRUCT);
1555 _dbus_type_reader_recurse (reader, &sub);
1557 if (!read_struct_of_structs (block, &sub))
1560 NEXT_EXPECTING_TRUE (&sub);
1561 if (!read_struct_of_structs (block, &sub))
1564 NEXT_EXPECTING_FALSE (&sub);
1570 write_array_of_int32 (DataBlock *block,
1571 DBusTypeWriter *writer)
1574 DataBlockState saved;
1577 data_block_save (block, &saved);
1579 if (!_dbus_type_writer_recurse_array (writer,
1580 DBUS_TYPE_INT32_AS_STRING,
1584 v = SAMPLE_INT32_ALTERNATE;
1585 if (!_dbus_type_writer_write_basic (&sub,
1589 data_block_restore (block, &saved);
1594 if (!_dbus_type_writer_write_basic (&sub,
1598 data_block_restore (block, &saved);
1603 if (!_dbus_type_writer_write_basic (&sub,
1607 data_block_restore (block, &saved);
1611 if (!_dbus_type_writer_unrecurse (writer, &sub))
1613 data_block_restore (block, &saved);
1621 read_array_of_int32 (DataBlock *block,
1622 DBusTypeReader *reader)
1627 check_expected_type (reader, DBUS_TYPE_ARRAY);
1629 _dbus_type_reader_recurse (reader, &sub);
1631 check_expected_type (&sub, DBUS_TYPE_INT32);
1633 _dbus_type_reader_read_basic (&sub,
1634 (dbus_int32_t*) &v);
1636 _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1638 NEXT_EXPECTING_TRUE (&sub);
1639 check_expected_type (&sub, DBUS_TYPE_INT32);
1641 _dbus_type_reader_read_basic (&sub,
1642 (dbus_int32_t*) &v);
1644 _dbus_assert (v == SAMPLE_INT32);
1646 NEXT_EXPECTING_TRUE (&sub);
1647 check_expected_type (&sub, DBUS_TYPE_INT32);
1649 _dbus_type_reader_read_basic (&sub,
1650 (dbus_int32_t*) &v);
1652 _dbus_assert (v == SAMPLE_INT32);
1654 NEXT_EXPECTING_FALSE (&sub);
1661 write_array_of_int32_empty (DataBlock *block,
1662 DBusTypeWriter *writer)
1664 DataBlockState saved;
1667 data_block_save (block, &saved);
1669 if (!_dbus_type_writer_recurse_array (writer,
1670 DBUS_TYPE_INT32_AS_STRING,
1674 if (!_dbus_type_writer_unrecurse (writer, &sub))
1676 data_block_restore (block, &saved);
1684 read_array_of_int32_empty (DataBlock *block,
1685 DBusTypeReader *reader)
1687 check_expected_type (reader, DBUS_TYPE_ARRAY);
1689 /* We are iterating over values not types. Thus we can't recurse
1692 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1698 write_array_of_array_of_int32 (DataBlock *block,
1699 DBusTypeWriter *writer)
1701 DataBlockState saved;
1704 data_block_save (block, &saved);
1706 if (!_dbus_type_writer_recurse_array (writer,
1707 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1711 if (!write_array_of_int32 (block, &sub))
1713 data_block_restore (block, &saved);
1717 if (!write_array_of_int32 (block, &sub))
1719 data_block_restore (block, &saved);
1723 if (!write_array_of_int32_empty (block, &sub))
1725 data_block_restore (block, &saved);
1729 if (!write_array_of_int32 (block, &sub))
1731 data_block_restore (block, &saved);
1735 if (!_dbus_type_writer_unrecurse (writer, &sub))
1737 data_block_restore (block, &saved);
1745 read_array_of_array_of_int32 (DataBlock *block,
1746 DBusTypeReader *reader)
1750 check_expected_type (reader, DBUS_TYPE_ARRAY);
1752 _dbus_type_reader_recurse (reader, &sub);
1754 if (!read_array_of_int32 (block, &sub))
1757 NEXT_EXPECTING_TRUE (&sub);
1758 if (!read_array_of_int32 (block, &sub))
1761 NEXT_EXPECTING_TRUE (&sub);
1762 if (!read_array_of_int32_empty (block, &sub))
1765 NEXT_EXPECTING_TRUE (&sub);
1766 if (!read_array_of_int32 (block, &sub))
1769 NEXT_EXPECTING_FALSE (&sub);
1776 write_array_of_array_of_int32_empty (DataBlock *block,
1777 DBusTypeWriter *writer)
1779 DataBlockState saved;
1782 data_block_save (block, &saved);
1784 if (!_dbus_type_writer_recurse_array (writer,
1785 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1789 if (!_dbus_type_writer_unrecurse (writer, &sub))
1791 data_block_restore (block, &saved);
1799 read_array_of_array_of_int32_empty (DataBlock *block,
1800 DBusTypeReader *reader)
1802 check_expected_type (reader, DBUS_TYPE_ARRAY);
1804 /* We are iterating over values, not types. Thus
1805 * we can't recurse in here.
1808 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1814 write_array_of_array_of_array_of_int32 (DataBlock *block,
1815 DBusTypeWriter *writer)
1817 DataBlockState saved;
1820 data_block_save (block, &saved);
1822 if (!_dbus_type_writer_recurse_array (writer,
1823 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1827 if (!write_array_of_array_of_int32 (block, &sub))
1829 data_block_restore (block, &saved);
1833 if (!write_array_of_array_of_int32 (block, &sub))
1835 data_block_restore (block, &saved);
1839 if (!write_array_of_array_of_int32_empty (block, &sub))
1841 data_block_restore (block, &saved);
1845 if (!_dbus_type_writer_unrecurse (writer, &sub))
1847 data_block_restore (block, &saved);
1855 read_array_of_array_of_array_of_int32 (DataBlock *block,
1856 DBusTypeReader *reader)
1860 check_expected_type (reader, DBUS_TYPE_ARRAY);
1862 _dbus_type_reader_recurse (reader, &sub);
1864 if (!read_array_of_array_of_int32 (block, &sub))
1867 NEXT_EXPECTING_TRUE (&sub);
1868 if (!read_array_of_array_of_int32 (block, &sub))
1871 NEXT_EXPECTING_TRUE (&sub);
1872 if (!read_array_of_array_of_int32_empty (block, &sub))
1875 NEXT_EXPECTING_FALSE (&sub);
1881 write_struct_of_array_of_int32 (DataBlock *block,
1882 DBusTypeWriter *writer)
1884 DataBlockState saved;
1887 data_block_save (block, &saved);
1889 if (!_dbus_type_writer_recurse_struct (writer,
1893 if (!write_array_of_int32 (block, &sub))
1895 data_block_restore (block, &saved);
1899 if (!write_array_of_int32_empty (block, &sub))
1901 data_block_restore (block, &saved);
1905 if (!_dbus_type_writer_unrecurse (writer, &sub))
1907 data_block_restore (block, &saved);
1915 read_struct_of_array_of_int32 (DataBlock *block,
1916 DBusTypeReader *reader)
1920 check_expected_type (reader, DBUS_TYPE_STRUCT);
1922 _dbus_type_reader_recurse (reader, &sub);
1924 check_expected_type (&sub, DBUS_TYPE_ARRAY);
1926 if (!read_array_of_int32 (block, &sub))
1929 NEXT_EXPECTING_TRUE (&sub);
1930 if (!read_array_of_int32_empty (block, &sub))
1933 NEXT_EXPECTING_FALSE (&sub);
1939 write_struct_of_struct_of_array_of_int32 (DataBlock *block,
1940 DBusTypeWriter *writer)
1942 DataBlockState saved;
1945 data_block_save (block, &saved);
1947 if (!_dbus_type_writer_recurse_struct (writer,
1951 if (!write_struct_of_array_of_int32 (block, &sub))
1953 data_block_restore (block, &saved);
1956 if (!write_struct_of_array_of_int32 (block, &sub))
1958 data_block_restore (block, &saved);
1961 if (!write_struct_of_array_of_int32 (block, &sub))
1963 data_block_restore (block, &saved);
1967 if (!_dbus_type_writer_unrecurse (writer, &sub))
1969 data_block_restore (block, &saved);
1977 read_struct_of_struct_of_array_of_int32 (DataBlock *block,
1978 DBusTypeReader *reader)
1982 check_expected_type (reader, DBUS_TYPE_STRUCT);
1984 _dbus_type_reader_recurse (reader, &sub);
1986 if (!read_struct_of_array_of_int32 (block, &sub))
1989 NEXT_EXPECTING_TRUE (&sub);
1990 if (!read_struct_of_array_of_int32 (block, &sub))
1993 NEXT_EXPECTING_TRUE (&sub);
1994 if (!read_struct_of_array_of_int32 (block, &sub))
1997 NEXT_EXPECTING_FALSE (&sub);
2003 write_array_of_struct_of_int32 (DataBlock *block,
2004 DBusTypeWriter *writer)
2006 DataBlockState saved;
2009 data_block_save (block, &saved);
2011 if (!_dbus_type_writer_recurse_array (writer,
2012 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2013 DBUS_TYPE_INT32_AS_STRING
2014 DBUS_TYPE_INT32_AS_STRING
2015 DBUS_STRUCT_END_CHAR_AS_STRING,
2019 if (!write_struct_of_int32 (block, &sub))
2021 data_block_restore (block, &saved);
2025 if (!write_struct_of_int32 (block, &sub))
2027 data_block_restore (block, &saved);
2031 if (!write_struct_of_int32 (block, &sub))
2033 data_block_restore (block, &saved);
2037 if (!_dbus_type_writer_unrecurse (writer, &sub))
2039 data_block_restore (block, &saved);
2047 read_array_of_struct_of_int32 (DataBlock *block,
2048 DBusTypeReader *reader)
2052 check_expected_type (reader, DBUS_TYPE_ARRAY);
2054 _dbus_type_reader_recurse (reader, &sub);
2056 check_expected_type (&sub, DBUS_TYPE_STRUCT);
2058 if (!read_struct_of_int32 (block, &sub))
2061 NEXT_EXPECTING_TRUE (&sub);
2063 if (!read_struct_of_int32 (block, &sub))
2066 NEXT_EXPECTING_TRUE (&sub);
2068 if (!read_struct_of_int32 (block, &sub))
2071 NEXT_EXPECTING_FALSE (&sub);
2078 write_array_of_array_of_struct_of_int32 (DataBlock *block,
2079 DBusTypeWriter *writer)
2081 DataBlockState saved;
2084 data_block_save (block, &saved);
2086 if (!_dbus_type_writer_recurse_array (writer,
2087 DBUS_TYPE_ARRAY_AS_STRING
2088 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2089 DBUS_TYPE_INT32_AS_STRING
2090 DBUS_TYPE_INT32_AS_STRING
2091 DBUS_STRUCT_END_CHAR_AS_STRING,
2095 if (!write_array_of_struct_of_int32 (block, &sub))
2097 data_block_restore (block, &saved);
2101 if (!write_array_of_struct_of_int32 (block, &sub))
2103 data_block_restore (block, &saved);
2107 if (!write_array_of_struct_of_int32 (block, &sub))
2109 data_block_restore (block, &saved);
2113 if (!_dbus_type_writer_unrecurse (writer, &sub))
2115 data_block_restore (block, &saved);
2123 read_array_of_array_of_struct_of_int32 (DataBlock *block,
2124 DBusTypeReader *reader)
2128 check_expected_type (reader, DBUS_TYPE_ARRAY);
2130 _dbus_type_reader_recurse (reader, &sub);
2132 check_expected_type (&sub, DBUS_TYPE_ARRAY);
2134 if (!read_array_of_struct_of_int32 (block, &sub))
2137 NEXT_EXPECTING_TRUE (&sub);
2139 if (!read_array_of_struct_of_int32 (block, &sub))
2142 NEXT_EXPECTING_TRUE (&sub);
2144 if (!read_array_of_struct_of_int32 (block, &sub))
2147 NEXT_EXPECTING_FALSE (&sub);
2153 write_struct_of_array_of_struct_of_int32 (DataBlock *block,
2154 DBusTypeWriter *writer)
2156 DataBlockState saved;
2159 data_block_save (block, &saved);
2161 if (!_dbus_type_writer_recurse_struct (writer,
2165 if (!write_array_of_struct_of_int32 (block, &sub))
2167 data_block_restore (block, &saved);
2170 if (!write_array_of_struct_of_int32 (block, &sub))
2172 data_block_restore (block, &saved);
2175 if (!write_array_of_struct_of_int32 (block, &sub))
2177 data_block_restore (block, &saved);
2181 if (!_dbus_type_writer_unrecurse (writer, &sub))
2183 data_block_restore (block, &saved);
2191 read_struct_of_array_of_struct_of_int32 (DataBlock *block,
2192 DBusTypeReader *reader)
2196 check_expected_type (reader, DBUS_TYPE_STRUCT);
2198 _dbus_type_reader_recurse (reader, &sub);
2200 if (!read_array_of_struct_of_int32 (block, &sub))
2203 NEXT_EXPECTING_TRUE (&sub);
2204 if (!read_array_of_struct_of_int32 (block, &sub))
2207 NEXT_EXPECTING_TRUE (&sub);
2208 if (!read_array_of_struct_of_int32 (block, &sub))
2211 NEXT_EXPECTING_FALSE (&sub);
2217 write_array_of_struct_of_array_of_int32 (DataBlock *block,
2218 DBusTypeWriter *writer)
2220 DataBlockState saved;
2223 data_block_save (block, &saved);
2225 if (!_dbus_type_writer_recurse_array (writer,
2226 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2227 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
2228 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
2229 DBUS_STRUCT_END_CHAR_AS_STRING,
2233 if (!write_struct_of_array_of_int32 (block, &sub))
2235 data_block_restore (block, &saved);
2239 if (!write_struct_of_array_of_int32 (block, &sub))
2241 data_block_restore (block, &saved);
2245 if (!write_struct_of_array_of_int32 (block, &sub))
2247 data_block_restore (block, &saved);
2251 if (!_dbus_type_writer_unrecurse (writer, &sub))
2253 data_block_restore (block, &saved);
2261 read_array_of_struct_of_array_of_int32 (DataBlock *block,
2262 DBusTypeReader *reader)
2266 check_expected_type (reader, DBUS_TYPE_ARRAY);
2268 _dbus_type_reader_recurse (reader, &sub);
2270 check_expected_type (&sub, DBUS_TYPE_STRUCT);
2272 if (!read_struct_of_array_of_int32 (block, &sub))
2275 NEXT_EXPECTING_TRUE (&sub);
2277 if (!read_struct_of_array_of_int32 (block, &sub))
2280 NEXT_EXPECTING_TRUE (&sub);
2282 if (!read_struct_of_array_of_int32 (block, &sub))
2285 NEXT_EXPECTING_FALSE (&sub);
2295 ITEM_STRUCT_OF_INT32,
2296 ITEM_STRUCT_OF_STRUCTS,
2297 ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2299 ITEM_ARRAY_OF_INT32,
2300 ITEM_ARRAY_OF_INT32_EMPTY,
2301 ITEM_ARRAY_OF_ARRAY_OF_INT32,
2302 ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2303 ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2305 ITEM_STRUCT_OF_ARRAY_OF_INT32,
2306 ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2308 ITEM_ARRAY_OF_STRUCT_OF_INT32,
2309 ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2311 ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2312 ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2318 typedef dbus_bool_t (* WriteItemFunc) (DataBlock *block,
2319 DBusTypeWriter *writer);
2320 typedef dbus_bool_t (* ReadItemFunc) (DataBlock *block,
2321 DBusTypeReader *reader);
2327 WriteItemFunc write_item_func;
2328 ReadItemFunc read_item_func;
2331 static CheckMarshalItem items[] = {
2333 ITEM_INT32, write_int32, read_int32 },
2334 { "struct with two int32",
2335 ITEM_STRUCT_OF_INT32, write_struct_of_int32, read_struct_of_int32 },
2336 { "struct with three structs of two int32",
2337 ITEM_STRUCT_OF_STRUCTS, write_struct_of_structs, read_struct_of_structs },
2338 { "struct of two structs of three structs of two int32",
2339 ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2340 write_struct_of_structs_of_structs,
2341 read_struct_of_structs_of_structs },
2343 ITEM_ARRAY_OF_INT32, write_array_of_int32, read_array_of_int32 },
2344 { "empty array of int32",
2345 ITEM_ARRAY_OF_INT32_EMPTY, write_array_of_int32_empty, read_array_of_int32_empty },
2346 { "array of array of int32",
2347 ITEM_ARRAY_OF_ARRAY_OF_INT32,
2348 write_array_of_array_of_int32, read_array_of_array_of_int32 },
2349 { "empty array of array of int32",
2350 ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2351 write_array_of_array_of_int32_empty, read_array_of_array_of_int32_empty },
2352 { "array of array of array of int32",
2353 ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2354 write_array_of_array_of_array_of_int32, read_array_of_array_of_array_of_int32 },
2355 { "struct of array of int32",
2356 ITEM_STRUCT_OF_ARRAY_OF_INT32, write_struct_of_array_of_int32, read_struct_of_array_of_int32 },
2357 { "struct of struct of array of int32",
2358 ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2359 write_struct_of_struct_of_array_of_int32, read_struct_of_struct_of_array_of_int32 },
2360 { "array of struct of int32",
2361 ITEM_ARRAY_OF_STRUCT_OF_INT32, write_array_of_struct_of_int32, read_array_of_struct_of_int32 },
2362 { "array of array of struct of int32",
2363 ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2364 write_array_of_array_of_struct_of_int32, read_array_of_array_of_struct_of_int32 },
2366 { "struct of array of struct of int32",
2367 ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2368 write_struct_of_array_of_struct_of_int32, read_struct_of_array_of_struct_of_int32 },
2369 { "array of struct of array of int32",
2370 ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2371 write_array_of_struct_of_array_of_int32, read_array_of_struct_of_array_of_int32 },
2376 /* Array of items from the above items[]; -1 terminated */
2380 static TestRun runs[] = {
2381 { { ITEM_INVALID } },
2384 { { ITEM_INT32, ITEM_INVALID } },
2385 { { ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2386 { { ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2388 /* STRUCT_OF_INT32 */
2389 { { ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2390 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2391 { { ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2392 { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2393 { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2395 /* STRUCT_OF_STRUCTS */
2396 { { ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2397 { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2398 { { ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2399 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2400 { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2401 { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2403 /* STRUCT_OF_STRUCTS_OF_STRUCTS */
2404 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2405 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2406 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2407 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2408 { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2409 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2411 /* ARRAY_OF_INT32 */
2412 { { ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2413 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2414 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2415 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2416 { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2417 { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2418 { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2419 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2420 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2421 { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2423 /* ARRAY_OF_ARRAY_OF_INT32 */
2424 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2425 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2426 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2427 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2428 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2429 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2430 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2431 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2432 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2433 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2435 /* ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32 */
2436 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2437 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2438 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2439 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2440 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2441 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2442 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2443 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2444 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2445 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2447 /* STRUCT_OF_ARRAY_OF_INT32 */
2448 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2449 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2450 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2451 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2452 { { ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2453 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2455 /* STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32 */
2456 { { ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2458 /* ARRAY_OF_STRUCT_OF_INT32 */
2459 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2460 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2461 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2462 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2463 { { ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2464 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2466 /* ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32 */
2467 { { ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2469 /* STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32 */
2470 { { ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2472 /* ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32 */
2473 { { ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2478 perform_one_run (DataBlock *block,
2482 DBusTypeReader reader;
2483 DBusTypeWriter writer;
2485 DataBlockState saved;
2491 _dbus_verbose ("run byteorder %s items ",
2492 byte_order == DBUS_LITTLE_ENDIAN ? "little" : "big");
2494 while (run->items[i] != ITEM_INVALID)
2496 CheckMarshalItem *item = &items[run->items[i]];
2498 _dbus_verbose ("%s ", item->desc);
2501 _dbus_verbose (" = %d items\n", i);
2504 data_block_save (block, &saved);
2506 data_block_init_reader_writer (block,
2511 while (run->items[i] != ITEM_INVALID)
2513 CheckMarshalItem *item = &items[run->items[i]];
2515 _dbus_verbose (">>writing %s\n", item->desc);
2517 if (!(* item->write_item_func) (block, &writer))
2523 while (run->items[i] != ITEM_INVALID)
2525 CheckMarshalItem *item = &items[run->items[i]];
2527 _dbus_verbose (">>data for reading %s\n", item->desc);
2529 _dbus_verbose_bytes_of_string (reader.type_str, 0,
2530 _dbus_string_get_length (reader.type_str));
2531 _dbus_verbose_bytes_of_string (reader.value_str, 0,
2532 _dbus_string_get_length (reader.value_str));
2534 _dbus_verbose (">>reading %s\n", item->desc);
2536 if (!(* item->read_item_func) (block, &reader))
2539 _dbus_type_reader_next (&reader);
2547 data_block_restore (block, &saved);
2552 perform_all_runs (int byte_order,
2561 if (!data_block_init (&block))
2564 if (!_dbus_string_lengthen (&block.signature, initial_offset))
2567 if (!_dbus_string_lengthen (&block.body, initial_offset))
2571 while (i < _DBUS_N_ELEMENTS (runs))
2573 if (!perform_one_run (&block, byte_order, &runs[i]))
2582 data_block_free (&block);
2588 perform_all_items (int byte_order,
2598 if (!data_block_init (&block))
2602 if (!_dbus_string_lengthen (&block.signature, initial_offset))
2605 if (!_dbus_string_lengthen (&block.body, initial_offset))
2608 /* Create a run containing all the items */
2610 while (i < _DBUS_N_ELEMENTS (items))
2612 _dbus_assert (i == items[i].which);
2614 run.items[i] = items[i].which;
2619 run.items[i] = ITEM_INVALID;
2621 if (!perform_one_run (&block, byte_order, &run))
2627 data_block_free (&block);
2633 recursive_marshal_test_iteration (void *data)
2640 if (!perform_all_runs (DBUS_LITTLE_ENDIAN, i))
2642 if (!perform_all_runs (DBUS_BIG_ENDIAN, i))
2644 if (!perform_all_items (DBUS_LITTLE_ENDIAN, i))
2646 if (!perform_all_items (DBUS_BIG_ENDIAN, i))
2655 typedef struct TestTypeNode TestTypeNode;
2656 typedef struct TestTypeNodeClass TestTypeNodeClass;
2657 typedef struct TestTypeNodeContainer TestTypeNodeContainer;
2658 typedef struct TestTypeNodeContainerClass TestTypeNodeContainerClass;
2662 const TestTypeNodeClass *klass;
2663 void *data; /* some data, such as the particular value we wrote that we expect to read again */
2666 struct TestTypeNodeContainer
2672 struct TestTypeNodeClass
2678 dbus_bool_t (* construct) (TestTypeNode *node);
2679 void (* destroy) (TestTypeNode *node);
2681 dbus_bool_t (* write_value) (TestTypeNode *node,
2683 DBusTypeWriter *writer);
2684 dbus_bool_t (* read_value) (TestTypeNode *node,
2686 DBusTypeReader *reader);
2687 dbus_bool_t (* build_signature) (TestTypeNode *node,
2691 struct TestTypeNodeContainerClass
2693 TestTypeNodeClass base;
2696 static dbus_bool_t int32_write_value (TestTypeNode *node,
2698 DBusTypeWriter *writer);
2699 static dbus_bool_t int32_read_value (TestTypeNode *node,
2701 DBusTypeReader *reader);
2702 static dbus_bool_t struct_1_write_value (TestTypeNode *node,
2704 DBusTypeWriter *writer);
2705 static dbus_bool_t struct_1_read_value (TestTypeNode *node,
2707 DBusTypeReader *reader);
2708 static dbus_bool_t struct_1_build_signature (TestTypeNode *node,
2710 static dbus_bool_t struct_2_write_value (TestTypeNode *node,
2712 DBusTypeWriter *writer);
2713 static dbus_bool_t struct_2_read_value (TestTypeNode *node,
2715 DBusTypeReader *reader);
2716 static dbus_bool_t struct_2_build_signature (TestTypeNode *node,
2718 static dbus_bool_t array_build_signature (TestTypeNode *node,
2720 static dbus_bool_t array_1_write_value (TestTypeNode *node,
2722 DBusTypeWriter *writer);
2723 static dbus_bool_t array_1_read_value (TestTypeNode *node,
2725 DBusTypeReader *reader);
2726 static dbus_bool_t array_0_write_value (TestTypeNode *node,
2728 DBusTypeWriter *writer);
2729 static dbus_bool_t array_0_read_value (TestTypeNode *node,
2731 DBusTypeReader *reader);
2732 static dbus_bool_t array_2_write_value (TestTypeNode *node,
2734 DBusTypeWriter *writer);
2735 static dbus_bool_t array_2_read_value (TestTypeNode *node,
2737 DBusTypeReader *reader);
2739 static void container_destroy (TestTypeNode *node);
2742 static const TestTypeNodeClass int32_class = {
2744 sizeof (TestTypeNode),
2752 static const TestTypeNodeClass uint32_class = {
2754 sizeof (TestTypeNode),
2757 int32_write_value, /* recycle from int32 */
2758 int32_read_value, /* recycle from int32 */
2762 static const TestTypeNodeClass struct_1_class = {
2764 sizeof (TestTypeNodeContainer),
2767 struct_1_write_value,
2768 struct_1_read_value,
2769 struct_1_build_signature
2772 static const TestTypeNodeClass struct_2_class = {
2774 sizeof (TestTypeNodeContainer),
2777 struct_2_write_value,
2778 struct_2_read_value,
2779 struct_2_build_signature
2782 static const TestTypeNodeClass array_0_class = {
2784 sizeof (TestTypeNodeContainer),
2787 array_0_write_value,
2789 array_build_signature
2792 static const TestTypeNodeClass array_1_class = {
2794 sizeof (TestTypeNodeContainer),
2797 array_1_write_value,
2799 array_build_signature
2802 static const TestTypeNodeClass array_2_class = {
2804 sizeof (TestTypeNodeContainer),
2807 array_2_write_value,
2809 array_build_signature
2812 static const TestTypeNodeClass* const
2818 static const TestTypeNodeClass* const
2819 container_nodes[] = {
2827 static TestTypeNode*
2828 node_new (const TestTypeNodeClass *klass)
2832 node = dbus_malloc0 (klass->instance_size);
2836 node->klass = klass;
2838 if (klass->construct)
2840 if (!(* klass->construct) (node))
2851 node_destroy (TestTypeNode *node)
2853 if (node->klass->destroy)
2854 (* node->klass->destroy) (node);
2859 node_write_value (TestTypeNode *node,
2861 DBusTypeWriter *writer)
2863 return (* node->klass->write_value) (node, block, writer);
2867 node_read_value (TestTypeNode *node,
2869 DBusTypeReader *reader)
2871 return (* node->klass->read_value) (node, block, reader);
2875 node_build_signature (TestTypeNode *node,
2878 if (node->klass->build_signature)
2879 return (* node->klass->build_signature) (node, str);
2881 return _dbus_string_append_byte (str, node->klass->typecode);
2885 node_append_child (TestTypeNode *node,
2886 TestTypeNode *child)
2888 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2890 _dbus_assert (node->klass->instance_size >= (int) sizeof (TestTypeNodeContainer));
2892 return _dbus_list_append (&container->children, child);
2897 const DBusString *signature;
2901 TestTypeNode **nodes;
2903 } NodeIterationData;
2906 run_test_nodes_iteration (void *data)
2908 NodeIterationData *nid = data;
2909 DBusTypeReader reader;
2910 DBusTypeWriter writer;
2914 * 1. write the value
2915 * 2. strcmp-compare with the signature we built
2917 * 4. type-iterate the signature and the value and see if they are the same type-wise
2919 data_block_init_reader_writer (nid->block,
2924 while (i < nid->n_nodes)
2926 if (!node_write_value (nid->nodes[i], nid->block, &writer))
2932 if (!_dbus_string_equal_substring (nid->signature, 0, _dbus_string_get_length (nid->signature),
2933 &nid->block->signature, nid->type_offset))
2935 _dbus_warn ("Expected signature '%s' and got '%s' with initial offset %d\n",
2936 _dbus_string_get_const_data (nid->signature),
2937 _dbus_string_get_const_data_len (&nid->block->signature, nid->type_offset, 0),
2939 _dbus_assert_not_reached ("wrong signature");
2943 while (i < nid->n_nodes)
2945 if (!node_read_value (nid->nodes[i], nid->block, &reader))
2948 if (i + 1 == nid->n_nodes)
2949 NEXT_EXPECTING_FALSE (&reader);
2951 NEXT_EXPECTING_TRUE (&reader);
2956 /* FIXME type-iterate both signature and value */
2962 run_test_nodes_in_one_configuration (TestTypeNode **nodes,
2964 const DBusString *signature,
2969 NodeIterationData nid;
2971 if (!data_block_init (&block))
2972 _dbus_assert_not_reached ("no memory");
2974 if (!_dbus_string_lengthen (&block.signature, initial_offset))
2975 _dbus_assert_not_reached ("no memory");
2977 if (!_dbus_string_lengthen (&block.body, initial_offset))
2978 _dbus_assert_not_reached ("no memory");
2980 nid.signature = signature;
2982 nid.type_offset = initial_offset;
2984 nid.n_nodes = n_nodes;
2985 nid.byte_order = byte_order;
2987 _dbus_test_oom_handling ("running test node",
2988 run_test_nodes_iteration,
2991 data_block_free (&block);
2995 run_test_nodes (TestTypeNode **nodes,
2999 DBusString signature;
3001 if (!_dbus_string_init (&signature))
3002 _dbus_assert_not_reached ("no memory");
3007 if (! node_build_signature (nodes[i], &signature))
3008 _dbus_assert_not_reached ("no memory");
3013 _dbus_verbose (">>> test nodes with signature '%s'\n",
3014 _dbus_string_get_const_data (&signature));
3019 run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
3020 DBUS_LITTLE_ENDIAN, i);
3021 run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
3022 DBUS_BIG_ENDIAN, i);
3027 _dbus_string_free (&signature);
3030 #define N_VALUES (_DBUS_N_ELEMENTS (basic_nodes) * _DBUS_N_ELEMENTS (container_nodes) + _DBUS_N_ELEMENTS (basic_nodes))
3032 static TestTypeNode*
3033 value_generator (int *ip)
3036 const TestTypeNodeClass *child_klass;
3037 const TestTypeNodeClass *container_klass;
3038 TestTypeNode *child;
3045 else if (i < _DBUS_N_ELEMENTS (basic_nodes))
3047 node = node_new (basic_nodes[i]);
3051 /* imagine an array:
3052 * container 0 of basic 0
3053 * container 0 of basic 1
3054 * container 0 of basic 2
3055 * container 1 of basic 0
3056 * container 1 of basic 1
3057 * container 1 of basic 2
3059 i -= _DBUS_N_ELEMENTS (basic_nodes);
3061 container_klass = container_nodes[i / _DBUS_N_ELEMENTS (basic_nodes)];
3062 child_klass = basic_nodes[i % _DBUS_N_ELEMENTS (basic_nodes)];
3064 node = node_new (container_klass);
3065 child = node_new (child_klass);
3067 node_append_child (node, child);
3070 *ip += 1; /* increment the generator */
3076 make_and_run_test_nodes (void)
3080 /* We try to do this in order of "complicatedness" so that test
3081 * failures tend to show up in the simplest test case that
3082 * demonstrates the failure. There are also some tests that run
3083 * more than once for this reason, first while going through simple
3084 * cases, second while going through a broader range of complex
3087 /* Each basic node. The basic nodes should include:
3089 * - each fixed-size type (in such a way that it has different values each time,
3090 * so we can tell if we mix two of them up)
3091 * - strings of length 0-9
3095 /* Each container node. The container nodes should include:
3097 * struct with 1 and 2 copies of the contained item
3098 * array with 0, 1, 2 copies of the contained item
3101 /* Let a "value" be a basic node, or a container containing a single basic node.
3102 * Let n_values be the number of such values i.e. (n_container * n_basic + n_basic)
3103 * When iterating through all values to make combinations, do the basic types
3104 * first and the containers second.
3106 /* Each item is shown with its number of iterations so we can keep a handle
3110 /* n_basic iterations */
3111 _dbus_verbose (">>> >>> Each basic node by itself\n");
3112 for (i = 0; i < _DBUS_N_ELEMENTS (basic_nodes); i++)
3114 const TestTypeNodeClass *klass = basic_nodes[i];
3117 node = node_new (klass);
3119 run_test_nodes (&node, 1);
3121 node_destroy (node);
3124 /* n_container * n_basic iterations */
3125 _dbus_verbose (">>> >>> Each container of each basic (redundant with later tests)\n");
3126 for (i = 0; i < _DBUS_N_ELEMENTS (container_nodes); i++)
3128 const TestTypeNodeClass *container_klass = container_nodes[i];
3129 for (j = 0; j < _DBUS_N_ELEMENTS (basic_nodes); j++)
3131 const TestTypeNodeClass *child_klass = basic_nodes[j];
3132 TestTypeNode *child;
3133 TestTypeNode *container;
3135 container = node_new (container_klass);
3136 child = node_new (child_klass);
3138 node_append_child (container, child);
3140 run_test_nodes (&container, 1);
3142 node_destroy (container);
3146 /* n_values * n_values * 2 iterations */
3147 _dbus_verbose (">>> >>> Each value,value pair combination as toplevel, in both orders\n");
3149 TestTypeNode *nodes[2];
3152 while ((nodes[0] = value_generator (&i)))
3155 while ((nodes[1] = value_generator (&j)))
3157 run_test_nodes (nodes, 2);
3159 node_destroy (nodes[1]);
3162 node_destroy (nodes[0]);
3167 _dbus_verbose (">>> >>> All values in one big toplevel\n");
3169 TestTypeNode *nodes[N_VALUES];
3172 while ((nodes[i] = value_generator (&i)))
3175 run_test_nodes (nodes, N_VALUES);
3177 for (i = 0; i < N_VALUES; i++)
3178 node_destroy (nodes[i]);
3181 /* n_container * n_values iterations */
3182 _dbus_verbose (">>> >>> Each container containing each value\n");
3183 for (i = 0; i < _DBUS_N_ELEMENTS (container_nodes); i++)
3185 const TestTypeNodeClass *container_klass = container_nodes[i];
3186 TestTypeNode *child;
3189 while ((child = value_generator (&j)))
3191 TestTypeNode *container;
3193 container = node_new (container_klass);
3195 node_append_child (container, child);
3197 run_test_nodes (&container, 1);
3199 node_destroy (container);
3203 /* n_container * n_values - container of same container of values */
3205 /* n_container * n_values - container of same container of same container of values */
3207 /* n_container * n_container * n_values - container of container of values */
3208 /* n_container * n_container * n_container * n_values - container of container of container of values */
3210 /* n_values * n_values * n_values * 6 - each trio of value,value,value in all orders */
3212 /* n_values * n_values * 2 - each value,value pair inside STRUCT, in both orders */
3214 /* 1 - all values in one big STRUCT */
3217 dbus_bool_t _dbus_marshal_recursive_test (void);
3220 _dbus_marshal_recursive_test (void)
3222 /* The new comprehensive tests */
3225 make_and_run_test_nodes ();
3230 _dbus_test_oom_handling ("recursive marshaling",
3231 recursive_marshal_test_iteration,
3240 main (int argc, char **argv)
3242 _dbus_marshal_recursive_test ();
3252 * Implementations of each type node class
3259 int32_write_value (TestTypeNode *node,
3261 DBusTypeWriter *writer)
3263 /* also used for uint32 */
3264 dbus_int32_t v = _DBUS_POINTER_TO_INT (node->data);
3266 return _dbus_type_writer_write_basic (writer,
3267 node->klass->typecode,
3272 int32_read_value (TestTypeNode *node,
3274 DBusTypeReader *reader)
3276 /* also used for uint32 */
3279 check_expected_type (reader, node->klass->typecode);
3281 _dbus_type_reader_read_basic (reader,
3282 (dbus_int32_t*) &v);
3284 _dbus_assert (v == _DBUS_POINTER_TO_INT (node->data));
3290 struct_N_write_value (TestTypeNode *node,
3292 DBusTypeWriter *writer,
3295 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3296 DataBlockState saved;
3300 _dbus_assert (container->children != NULL);
3302 data_block_save (block, &saved);
3304 if (!_dbus_type_writer_recurse_struct (writer,
3309 while (i < n_copies)
3313 link = _dbus_list_get_first_link (&container->children);
3314 while (link != NULL)
3316 TestTypeNode *child = link->data;
3317 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3319 if (!node_write_value (child, block, &sub))
3321 data_block_restore (block, &saved);
3331 if (!_dbus_type_writer_unrecurse (writer, &sub))
3333 data_block_restore (block, &saved);
3341 struct_N_read_value (TestTypeNode *node,
3343 DBusTypeReader *reader,
3346 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3350 check_expected_type (reader, DBUS_TYPE_STRUCT);
3352 _dbus_type_reader_recurse (reader, &sub);
3355 while (i < n_copies)
3359 link = _dbus_list_get_first_link (&container->children);
3360 while (link != NULL)
3362 TestTypeNode *child = link->data;
3363 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3365 node_read_value (child, block, &sub);
3367 if (i == (n_copies - 1) && next == NULL)
3368 NEXT_EXPECTING_FALSE (&sub);
3370 NEXT_EXPECTING_TRUE (&sub);
3382 struct_N_build_signature (TestTypeNode *node,
3386 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3390 orig_len = _dbus_string_get_length (str);
3392 if (!_dbus_string_append_byte (str, DBUS_STRUCT_BEGIN_CHAR))
3396 while (i < n_copies)
3400 link = _dbus_list_get_first_link (&container->children);
3401 while (link != NULL)
3403 TestTypeNode *child = link->data;
3404 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3406 if (!node_build_signature (child, str))
3415 if (!_dbus_string_append_byte (str, DBUS_STRUCT_END_CHAR))
3421 _dbus_string_set_length (str, orig_len);
3426 struct_1_write_value (TestTypeNode *node,
3428 DBusTypeWriter *writer)
3430 return struct_N_write_value (node, block, writer, 1);
3434 struct_1_read_value (TestTypeNode *node,
3436 DBusTypeReader *reader)
3438 return struct_N_read_value (node, block, reader, 1);
3442 struct_1_build_signature (TestTypeNode *node,
3445 return struct_N_build_signature (node, str, 1);
3450 struct_2_write_value (TestTypeNode *node,
3452 DBusTypeWriter *writer)
3454 return struct_N_write_value (node, block, writer, 2);
3458 struct_2_read_value (TestTypeNode *node,
3460 DBusTypeReader *reader)
3462 return struct_N_read_value (node, block, reader, 2);
3466 struct_2_build_signature (TestTypeNode *node,
3469 return struct_N_build_signature (node, str, 2);
3473 array_N_write_value (TestTypeNode *node,
3475 DBusTypeWriter *writer,
3478 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3479 DataBlockState saved;
3481 DBusString element_signature;
3484 _dbus_assert (container->children != NULL);
3486 data_block_save (block, &saved);
3488 if (!_dbus_string_init (&element_signature))
3491 if (!node_build_signature (_dbus_list_get_first (&container->children),
3492 &element_signature))
3495 if (!_dbus_type_writer_recurse_array (writer,
3496 _dbus_string_get_const_data (&element_signature),
3501 while (i < n_copies)
3505 link = _dbus_list_get_first_link (&container->children);
3506 while (link != NULL)
3508 TestTypeNode *child = link->data;
3509 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3511 if (!node_write_value (child, block, &sub))
3520 if (!_dbus_type_writer_unrecurse (writer, &sub))
3526 data_block_restore (block, &saved);
3527 _dbus_string_free (&element_signature);
3532 array_N_read_value (TestTypeNode *node,
3534 DBusTypeReader *reader,
3537 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3541 check_expected_type (reader, DBUS_TYPE_ARRAY);
3545 _dbus_assert (!_dbus_type_reader_array_is_empty (reader));
3547 _dbus_type_reader_recurse (reader, &sub);
3550 while (i < n_copies)
3554 link = _dbus_list_get_first_link (&container->children);
3555 while (link != NULL)
3557 TestTypeNode *child = link->data;
3558 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3560 node_read_value (child, block, &sub);
3562 if (i == (n_copies - 1) && next == NULL)
3563 NEXT_EXPECTING_FALSE (&sub);
3565 NEXT_EXPECTING_TRUE (&sub);
3575 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
3582 array_build_signature (TestTypeNode *node,
3585 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3588 orig_len = _dbus_string_get_length (str);
3590 if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
3593 if (!node_build_signature (_dbus_list_get_first (&container->children),
3600 _dbus_string_set_length (str, orig_len);
3605 array_0_write_value (TestTypeNode *node,
3607 DBusTypeWriter *writer)
3609 return array_N_write_value (node, block, writer, 0);
3613 array_0_read_value (TestTypeNode *node,
3615 DBusTypeReader *reader)
3617 return array_N_read_value (node, block, reader, 0);
3622 array_1_write_value (TestTypeNode *node,
3624 DBusTypeWriter *writer)
3626 return array_N_write_value (node, block, writer, 1);
3630 array_1_read_value (TestTypeNode *node,
3632 DBusTypeReader *reader)
3634 return array_N_read_value (node, block, reader, 1);
3638 array_2_write_value (TestTypeNode *node,
3640 DBusTypeWriter *writer)
3642 return array_N_write_value (node, block, writer, 2);
3646 array_2_read_value (TestTypeNode *node,
3648 DBusTypeReader *reader)
3650 return array_N_read_value (node, block, reader, 2);
3654 container_destroy (TestTypeNode *node)
3656 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3659 link = _dbus_list_get_first_link (&container->children);
3660 while (link != NULL)
3662 TestTypeNode *child = link->data;
3663 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3665 node_destroy (child);
3667 _dbus_list_free_link (link);
3673 #endif /* DBUS_BUILD_TESTS */