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 void (* recurse) (DBusTypeReader *sub,
36 DBusTypeReader *parent);
37 int (* get_current_type) (DBusTypeReader *reader);
38 void (* next) (DBusTypeReader *reader,
43 first_type_in_signature (const DBusString *str,
48 t = _dbus_string_get_byte (str, pos);
50 if (t == DBUS_STRUCT_BEGIN_CHAR)
51 return DBUS_TYPE_STRUCT;
57 element_type_get_alignment (const DBusString *str,
60 return _dbus_type_get_alignment (first_type_in_signature (str, pos));
64 reader_init (DBusTypeReader *reader,
66 const DBusString *type_str,
68 const DBusString *value_str,
71 reader->byte_order = byte_order;
72 reader->type_str = type_str;
73 reader->type_pos = type_pos;
74 reader->value_str = value_str;
75 reader->value_pos = value_pos;
79 base_reader_recurse (DBusTypeReader *sub,
80 DBusTypeReader *parent)
82 /* point subreader at the same place as parent */
92 struct_reader_recurse (DBusTypeReader *sub,
93 DBusTypeReader *parent)
95 base_reader_recurse (sub, parent);
97 _dbus_assert (_dbus_string_get_byte (sub->type_str,
98 sub->type_pos) == DBUS_STRUCT_BEGIN_CHAR);
102 /* struct has 8 byte alignment */
103 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
105 sub->u.strct.finished = FALSE;
109 array_reader_recurse (DBusTypeReader *sub,
110 DBusTypeReader *parent)
112 dbus_uint32_t array_len;
115 _dbus_assert (!_dbus_type_reader_array_is_empty (parent));
117 base_reader_recurse (sub, parent);
119 /* point type_pos at the array element type */
122 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
124 _dbus_demarshal_basic_type (sub->value_str,
130 sub->u.array.len = array_len;
132 alignment = element_type_get_alignment (sub->type_str,
135 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
137 sub->u.array.element_type = first_type_in_signature (sub->type_str,
139 sub->u.array.start_pos = sub->value_pos;
141 _dbus_verbose (" type reader %p array start = %d array len = %d array element type = %s\n",
143 sub->u.array.start_pos,
145 _dbus_type_to_string (sub->u.array.element_type));
149 body_reader_get_current_type (DBusTypeReader *reader)
153 t = first_type_in_signature (reader->type_str,
160 struct_reader_get_current_type (DBusTypeReader *reader)
164 if (reader->u.strct.finished)
165 t = DBUS_TYPE_INVALID;
167 t = first_type_in_signature (reader->type_str,
174 array_reader_get_current_type (DBusTypeReader *reader)
179 /* return the array element type if elements remain, and
180 * TYPE_INVALID otherwise
183 end_pos = reader->u.array.start_pos + reader->u.array.len;
185 _dbus_assert (reader->value_pos <= end_pos);
186 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
188 if (reader->value_pos < end_pos)
189 t = reader->u.array.element_type;
191 t = DBUS_TYPE_INVALID;
197 skip_one_complete_type (const DBusString *type_str,
200 while (_dbus_string_get_byte (type_str, *type_pos) == DBUS_TYPE_ARRAY)
203 if (_dbus_string_get_byte (type_str, *type_pos) == DBUS_STRUCT_BEGIN_CHAR)
210 switch (_dbus_string_get_byte (type_str, *type_pos))
212 case DBUS_STRUCT_BEGIN_CHAR:
215 case DBUS_STRUCT_END_CHAR:
218 case DBUS_TYPE_INVALID:
219 _dbus_assert_not_reached ("unbalanced parens in signature");
230 skip_array_values (int element_type,
231 const DBusString *value_str,
235 dbus_uint32_t array_len;
239 pos = _DBUS_ALIGN_VALUE (*value_pos, 4);
241 _dbus_demarshal_basic_type (value_str,
247 alignment = _dbus_type_get_alignment (element_type);
249 pos = _DBUS_ALIGN_VALUE (pos, alignment);
251 *value_pos = pos + array_len;
255 base_reader_next (DBusTypeReader *reader,
258 switch (current_type)
260 case DBUS_TYPE_STRUCT:
261 /* Scan forward over the entire container contents */
265 /* Recurse into the struct */
266 _dbus_type_reader_recurse (reader, &sub);
268 /* Skip everything in this subreader */
269 while (_dbus_type_reader_next (&sub))
274 /* Now we are at the end of this container */
275 reader->type_pos = sub.type_pos;
276 reader->value_pos = sub.value_pos;
280 case DBUS_TYPE_ARRAY:
282 skip_array_values (first_type_in_signature (reader->type_str,
283 reader->type_pos + 1),
284 reader->value_str, &reader->value_pos, reader->byte_order);
285 skip_one_complete_type (reader->type_str, &reader->type_pos);
290 _dbus_marshal_skip_basic_type (reader->value_str,
291 current_type, reader->byte_order,
293 reader->type_pos += 1;
299 struct_reader_next (DBusTypeReader *reader,
304 base_reader_next (reader, current_type);
306 /* for STRUCT containers we return FALSE at the end of the struct,
307 * for INVALID we return FALSE at the end of the signature.
308 * In both cases we arrange for get_current_type() to return INVALID
309 * which is defined to happen iff we're at the end (no more next())
311 t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
312 if (t == DBUS_STRUCT_END_CHAR)
314 reader->type_pos += 1;
315 reader->u.strct.finished = TRUE;
320 array_reader_next (DBusTypeReader *reader,
323 /* Skip one array element */
326 end_pos = reader->u.array.start_pos + reader->u.array.len;
328 _dbus_assert (reader->value_pos < end_pos);
329 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
331 if (reader->u.array.element_type == DBUS_TYPE_STRUCT)
335 /* Recurse into the struct */
336 _dbus_type_reader_recurse (reader, &sub);
338 /* Skip everything in this element */
339 while (_dbus_type_reader_next (&sub))
344 /* Now we are at the end of this element */
345 reader->value_pos = sub.value_pos;
347 else if (reader->u.array.element_type == DBUS_TYPE_ARRAY)
349 skip_array_values (first_type_in_signature (reader->type_str,
350 reader->type_pos + 1),
351 reader->value_str, &reader->value_pos, reader->byte_order);
355 _dbus_marshal_skip_basic_type (reader->value_str,
356 current_type, reader->byte_order,
360 _dbus_assert (reader->value_pos <= end_pos);
362 if (reader->value_pos == end_pos)
364 skip_one_complete_type (reader->type_str,
369 static const DBusTypeReaderClass body_reader_class = {
371 NULL, /* body is always toplevel, so doesn't get recursed into */
372 body_reader_get_current_type,
376 static const DBusTypeReaderClass struct_reader_class = {
378 struct_reader_recurse,
379 struct_reader_get_current_type,
383 static const DBusTypeReaderClass array_reader_class = {
385 array_reader_recurse,
386 array_reader_get_current_type,
391 _dbus_type_reader_init (DBusTypeReader *reader,
393 const DBusString *type_str,
395 const DBusString *value_str,
398 reader->klass = &body_reader_class;
400 reader_init (reader, byte_order, type_str, type_pos,
401 value_str, value_pos);
403 _dbus_verbose (" type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
404 reader, reader->type_pos, reader->value_pos,
405 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
409 _dbus_type_reader_get_current_type (DBusTypeReader *reader)
413 t = (* reader->klass->get_current_type) (reader);
415 _dbus_assert (t != DBUS_STRUCT_END_CHAR);
416 _dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR);
419 _dbus_verbose (" type reader %p current type_pos = %d type = %s\n",
420 reader, reader->type_pos,
421 _dbus_type_to_string (t));
428 _dbus_type_reader_array_is_empty (DBusTypeReader *reader)
430 dbus_uint32_t array_len;
433 _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY,
436 len_pos = _DBUS_ALIGN_VALUE (reader->value_pos, 4);
438 _dbus_demarshal_basic_type (reader->value_str,
444 return array_len == 0;
448 _dbus_type_reader_read_basic (DBusTypeReader *reader,
454 t = _dbus_type_reader_get_current_type (reader);
456 next = reader->value_pos;
457 _dbus_demarshal_basic_type (reader->value_str,
463 _dbus_verbose (" type reader %p read basic type_pos = %d value_pos = %d next = %d remaining sig '%s'\n",
464 reader, reader->type_pos, reader->value_pos, next,
465 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
469 _dbus_type_reader_read_array_of_basic (DBusTypeReader *reader,
479 * Initialize a new reader pointing to the first type and
480 * corresponding value that's a child of the current container. It's
481 * an error to call this if the current type is a non-container.
483 * Note that DBusTypeReader traverses values, not types. So if you
484 * have an empty array of array of int, you can't recurse into it. You
485 * can only recurse into each element.
487 * @param reader the reader
488 * @param sub a reader to init pointing to the first child
491 _dbus_type_reader_recurse (DBusTypeReader *reader,
496 t = first_type_in_signature (reader->type_str, reader->type_pos);
500 case DBUS_TYPE_STRUCT:
501 sub->klass = &struct_reader_class;
503 case DBUS_TYPE_ARRAY:
504 sub->klass = &array_reader_class;
507 _dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t));
508 #ifndef DBUS_DISABLE_CHECKS
509 if (t == DBUS_TYPE_INVALID)
510 _dbus_warn ("You can't recurse into an empty array or off the end of a message body\n");
511 #endif /* DBUS_DISABLE_CHECKS */
513 _dbus_assert_not_reached ("don't yet handle recursing into this type");
516 (* sub->klass->recurse) (sub, reader);
518 _dbus_verbose (" type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
519 sub, sub->type_pos, sub->value_pos,
520 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
524 * Skip to the next value on this "level". e.g. the next field in a
525 * struct, the next value in an array, the next key or value in a
526 * dict. Returns FALSE at the end of the current container.
528 * @param reader the reader
529 * @returns FALSE if nothing more to read at or below this level
532 _dbus_type_reader_next (DBusTypeReader *reader)
536 t = _dbus_type_reader_get_current_type (reader);
538 _dbus_verbose (" type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
539 reader, reader->type_pos, reader->value_pos,
540 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
541 _dbus_type_to_string (t));
543 if (t == DBUS_TYPE_INVALID)
546 (* reader->klass->next) (reader, t);
548 _dbus_verbose (" type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
549 reader, reader->type_pos, reader->value_pos,
550 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
551 _dbus_type_to_string (_dbus_type_reader_get_current_type (reader)));
553 return _dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID;
567 _dbus_type_writer_init (DBusTypeWriter *writer,
569 DBusString *type_str,
571 DBusString *value_str,
574 writer->byte_order = byte_order;
575 writer->type_str = type_str;
576 writer->type_pos = type_pos;
577 writer->value_str = value_str;
578 writer->value_pos = value_pos;
579 writer->container_type = DBUS_TYPE_INVALID;
580 writer->inside_array = FALSE;
582 _dbus_verbose ("writer %p init remaining sig '%s'\n", writer,
583 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
587 _dbus_type_writer_write_basic_no_typecode (DBusTypeWriter *writer,
594 old_value_len = _dbus_string_get_length (writer->value_str);
596 if (!_dbus_marshal_basic_type (writer->value_str,
603 bytes_written = _dbus_string_get_length (writer->value_str) - old_value_len;
605 writer->value_pos += bytes_written;
610 /* If our parent is an array, things are a little bit complicated.
612 * The parent must have a complete element type, such as
613 * "i" or "aai" or "(ii)" or "a(ii)". There can't be
614 * unclosed parens, or an "a" with no following type.
616 * To recurse, the only allowed operation is to recurse into the
617 * first type in the element type. So for "i" you can't recurse, for
618 * "ai" you can recurse into the array, for "(ii)" you can recurse
621 * If you recurse into the array for "ai", then you must specify
622 * "i" for the element type of the array you recurse into.
624 * While inside an array at any level, we need to avoid writing to
625 * type_str, since the type only appears once for the whole array,
626 * it does not appear for each array element.
628 * While inside an array type_pos points to the expected next
629 * typecode, rather than the next place we could write a typecode.
632 writer_recurse_init_and_check (DBusTypeWriter *writer,
636 _dbus_type_writer_init (sub,
643 sub->container_type = container_type;
645 if (writer->inside_array || sub->container_type == DBUS_TYPE_ARRAY)
646 sub->inside_array = TRUE;
648 sub->inside_array = FALSE;
650 #ifndef DBUS_DISABLE_CHECKS
651 if (writer->inside_array)
655 expected = first_type_in_signature (writer->type_str, writer->type_pos);
657 if (expected != sub->container_type)
659 _dbus_warn ("Writing an element of type %s, but the expected type here is %s\n",
660 _dbus_type_to_string (sub->container_type),
661 _dbus_type_to_string (expected));
662 _dbus_assert_not_reached ("bad array element written");
665 #endif /* DBUS_DISABLE_CHECKS */
667 _dbus_verbose (" type writer %p recurse parent type_pos = %d value_pos = %d inside_array = %d container_type = %s remaining sig '%s'\n",
668 writer, writer->type_pos, writer->value_pos, writer->inside_array,
669 _dbus_type_to_string (writer->container_type),
670 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
671 _dbus_verbose (" type writer %p recurse sub type_pos = %d value_pos = %d inside_array = %d container_type = %s\n",
672 sub, sub->type_pos, sub->value_pos,
674 _dbus_type_to_string (sub->container_type));
678 write_or_verify_typecode (DBusTypeWriter *writer,
681 /* A subwriter inside an array will have type_pos pointing to the
682 * expected typecode; a writer not inside an array has type_pos
683 * pointing to the next place to insert a typecode.
685 _dbus_verbose (" type writer %p write_or_verify start type_pos = %d remaining sig '%s'\n",
686 writer, writer->type_pos,
687 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
689 if (writer->inside_array)
691 #ifndef DBUS_DISABLE_CHECKS
695 expected = _dbus_string_get_byte (writer->type_str, writer->type_pos);
697 if (expected != typecode)
699 _dbus_warn ("Array type requires that type %s be written, but %s was written\n",
700 _dbus_type_to_string (expected), _dbus_type_to_string (typecode));
701 _dbus_assert_not_reached ("bad type inserted somewhere inside an array");
704 #endif /* DBUS_DISABLE_CHECKS */
706 /* if immediately inside an array we'd always be appending an element,
707 * so the expected type doesn't change; if inside a struct or something
708 * below an array, we need to move through said struct or something.
710 if (writer->container_type != DBUS_TYPE_ARRAY)
711 writer->type_pos += 1;
715 if (!_dbus_string_insert_byte (writer->type_str,
720 writer->type_pos += 1;
723 _dbus_verbose (" type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
724 writer, writer->type_pos,
725 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
731 _dbus_type_writer_recurse (DBusTypeWriter *writer,
735 writer_recurse_init_and_check (writer, container_type, sub);
737 switch (container_type)
739 case DBUS_TYPE_STRUCT:
741 /* Ensure that we'll be able to add alignment padding and the typecode */
742 if (!_dbus_string_alloc_space (sub->value_str, 8))
745 if (!write_or_verify_typecode (sub, DBUS_STRUCT_BEGIN_CHAR))
746 _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
748 if (!_dbus_string_insert_bytes (sub->value_str,
750 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
752 _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
753 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
756 case DBUS_TYPE_ARRAY:
757 _dbus_assert_not_reached ("use recurse_array() for arrays");
760 _dbus_assert_not_reached ("container_type unhandled");
768 _dbus_type_writer_recurse_array (DBusTypeWriter *writer,
769 const char *element_type,
772 int element_type_len;
773 DBusString element_type_str;
774 dbus_uint32_t value = 0;
779 writer_recurse_init_and_check (writer, DBUS_TYPE_ARRAY, sub);
781 #ifndef DBUS_DISABLE_CHECKS
782 if (writer->container_type == DBUS_TYPE_ARRAY)
784 DBusString parent_elements;
786 _dbus_assert (element_type != NULL);
788 _dbus_string_init_const (&parent_elements,
789 _dbus_string_get_const_data_len (writer->type_str,
790 writer->u.array.element_type_pos + 1,
793 if (!_dbus_string_starts_with_c_str (&parent_elements, element_type))
795 _dbus_warn ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
797 _dbus_assert_not_reached ("incompatible type for child array");
800 #endif /* DBUS_DISABLE_CHECKS */
802 _dbus_string_init_const (&element_type_str, element_type);
803 element_type_len = _dbus_string_get_length (&element_type_str);
805 /* 4 bytes for the array length and 4 bytes possible padding */
806 if (!_dbus_string_alloc_space (sub->value_str, 8))
809 sub->type_pos += 1; /* move to point to the element type, since type_pos
810 * should be the expected type for further writes
812 sub->u.array.element_type_pos = sub->type_pos;
813 sub->u.array.element_type_len = element_type_len;
815 if (!writer->inside_array)
817 /* sub is a toplevel/outermost array so we need to write the type data */
819 /* alloc space for array typecode, element signature, possible 7
822 if (!_dbus_string_alloc_space (writer->type_str, 1 + element_type_len + 7))
825 if (!_dbus_string_insert_byte (writer->type_str,
828 _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
830 if (!_dbus_string_copy (&element_type_str, 0,
831 sub->type_str, sub->u.array.element_type_pos))
832 _dbus_assert_not_reached ("should not have failed to insert array element typecodes");
835 /* Write the length */
836 sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
838 if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
840 _dbus_assert_not_reached ("should not have failed to insert array len");
842 _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
844 /* Write alignment padding for array elements */
845 _dbus_string_init_const (&str, element_type);
846 alignment = element_type_get_alignment (&str, 0);
848 aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
849 if (aligned != sub->value_pos)
851 if (!_dbus_string_insert_bytes (sub->value_str,
853 aligned - sub->value_pos,
855 _dbus_assert_not_reached ("should not have failed to insert alignment padding");
857 sub->value_pos = aligned;
859 sub->u.array.start_pos = sub->value_pos;
861 _dbus_assert (sub->u.array.start_pos == sub->value_pos);
862 _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
864 _dbus_verbose (" type writer %p recurse array done remaining sig '%s'\n", sub,
865 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
871 _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
874 _dbus_assert (sub->type_pos > 0); /* can't be recursed if this fails */
876 _dbus_verbose (" type writer %p unrecurse type_pos = %d value_pos = %d inside_array = %d container_type = %s\n",
877 writer, writer->type_pos, writer->value_pos, writer->inside_array,
878 _dbus_type_to_string (writer->container_type));
879 _dbus_verbose (" type writer %p unrecurse sub type_pos = %d value_pos = %d inside_array = %d container_type = %s\n",
880 sub, sub->type_pos, sub->value_pos,
882 _dbus_type_to_string (sub->container_type));
884 if (sub->container_type == DBUS_TYPE_STRUCT)
886 if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
889 else if (sub->container_type == DBUS_TYPE_ARRAY)
893 /* Set the array length */
894 len = sub->value_pos - sub->u.array.start_pos;
895 _dbus_marshal_set_uint32 (sub->value_str,
897 sub->u.array.len_pos,
899 _dbus_verbose (" filled in sub array len to %u at len_pos %d\n",
900 len, sub->u.array.len_pos);
903 /* Now get type_pos right for the parent writer. Here are the cases:
905 * Cases !writer->inside_array:
906 * (in these cases we want to update to the new insertion point)
908 * - we recursed from STRUCT or INVALID into STRUCT and type_pos
909 * is the new insertion point in all cases
910 * writer->type_pos = sub->type_pos
912 * - we recursed from STRUCT or INVALID into ARRAY, so type_pos in
913 * the child is the array element type, and type_pos in the parent
914 * currently is the child array type but should be set to the
915 * insertion point just after the element type
916 * writer->type_pos = sub->element_type_pos + sub->element_type_len
918 * Cases where writer->inside_array:
919 * (in these cases we want to update to next expected write)
921 * - we recursed from STRUCT into STRUCT somewhere inside an array
922 * element; type_pos in parent is at the child's begin_struct, and
923 * type_pos in the child is at the next field type for the parent
924 * writer->type_pos = sub->type_pos
926 * - we recursed from STRUCT or INVALID into ARRAY somewhere inside
927 * an array element, so type_pos in the parent is at the child's
928 * array typecode, and type_pos in the child is at the array
930 * writer->type_pos = sub->element_type_pos + sub->element_type_len
932 * - we recursed from ARRAY into STRUCT, so type_pos in the
933 * parent is the element type starting with STRUCT,
934 * and type_pos in the child is just after the end_struct code
935 * writer->type_pos should remain as-is
937 * - we recursed from ARRAY into ARRAY, so type_pos in the
938 * parent is the element type starting with child's ARRAY code,
939 * type_pos in the child is the element type of the
941 * writer->type_pos should remain as-is
943 if (writer->container_type == DBUS_TYPE_ARRAY)
945 /* Don't do anything, because sub was an element, and the type
946 * of subsequent elements should be the same
949 else if (sub->container_type == DBUS_TYPE_ARRAY)
951 /* Jump to the next type in the parent's type signature,
952 * which is after our array element type
954 _dbus_assert (writer->container_type != DBUS_TYPE_ARRAY);
955 writer->type_pos = sub->u.array.element_type_pos + sub->u.array.element_type_len;
959 writer->type_pos = sub->type_pos;
962 writer->value_pos = sub->value_pos;
964 _dbus_verbose (" type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
965 writer, writer->type_pos, writer->value_pos,
966 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
972 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
978 /* First ensure that our type realloc will succeed */
979 if (!_dbus_string_alloc_space (writer->type_str, 1))
984 if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
987 if (!write_or_verify_typecode (writer, type))
988 _dbus_assert_not_reached ("failed to write typecode after prealloc");
993 _dbus_verbose (" type writer %p basic type_pos = %d value_pos = %d inside_array = %d\n",
994 writer, writer->type_pos, writer->value_pos, writer->inside_array);
1000 _dbus_type_writer_write_array (DBusTypeWriter *writer,
1009 /** @} */ /* end of DBusMarshal group */
1011 #ifdef DBUS_BUILD_TESTS
1012 #include "dbus-test.h"
1018 DBusString signature;
1029 data_block_init (DataBlock *block)
1031 if (!_dbus_string_init (&block->signature))
1034 if (!_dbus_string_init (&block->body))
1036 _dbus_string_free (&block->signature);
1044 data_block_free (DataBlock *block)
1046 _dbus_string_free (&block->signature);
1047 _dbus_string_free (&block->body);
1051 data_block_save (DataBlock *block,
1052 DataBlockState *state)
1054 state->saved_sig_len = _dbus_string_get_length (&block->signature);
1055 state->saved_body_len = _dbus_string_get_length (&block->body);
1059 data_block_restore (DataBlock *block,
1060 DataBlockState *state)
1062 /* These set_length should be shortening things so should always work */
1064 if (!_dbus_string_set_length (&block->signature,
1065 state->saved_sig_len))
1066 _dbus_assert_not_reached ("could not restore signature length");
1068 if (!_dbus_string_set_length (&block->body,
1069 state->saved_body_len))
1070 _dbus_assert_not_reached ("could not restore body length");
1074 data_block_init_reader_writer (DataBlock *block,
1076 DBusTypeReader *reader,
1077 DBusTypeWriter *writer)
1079 _dbus_type_reader_init (reader,
1082 _dbus_string_get_length (&block->signature),
1084 _dbus_string_get_length (&block->body));
1086 _dbus_type_writer_init (writer,
1089 _dbus_string_get_length (&block->signature),
1091 _dbus_string_get_length (&block->body));
1094 #define NEXT_EXPECTING_TRUE(reader) do { if (!_dbus_type_reader_next (reader)) \
1096 _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d\n", \
1097 _DBUS_FUNCTION_NAME, __LINE__); \
1098 _dbus_assert_not_reached ("test failed"); \
1102 #define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader)) \
1104 _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d\n", \
1105 _DBUS_FUNCTION_NAME, __LINE__); \
1106 _dbus_assert_not_reached ("test failed"); \
1108 check_expected_type (reader, DBUS_TYPE_INVALID); \
1111 #define SAMPLE_INT32 12345678
1112 #define SAMPLE_INT32_ALTERNATE 53781429
1114 write_int32 (DataBlock *block,
1115 DBusTypeWriter *writer)
1117 dbus_int32_t v = SAMPLE_INT32;
1119 return _dbus_type_writer_write_basic (writer,
1125 real_check_expected_type (DBusTypeReader *reader,
1127 const char *funcname,
1132 t = _dbus_type_reader_get_current_type (reader);
1136 _dbus_warn ("Read type %s while expecting %s at %s line %d\n",
1137 _dbus_type_to_string (t),
1138 _dbus_type_to_string (expected),
1145 #define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__)
1148 read_int32 (DataBlock *block,
1149 DBusTypeReader *reader)
1153 check_expected_type (reader, DBUS_TYPE_INT32);
1155 _dbus_type_reader_read_basic (reader,
1156 (dbus_int32_t*) &v);
1158 _dbus_assert (v == SAMPLE_INT32);
1164 write_struct_of_int32 (DataBlock *block,
1165 DBusTypeWriter *writer)
1168 DataBlockState saved;
1171 data_block_save (block, &saved);
1173 if (!_dbus_type_writer_recurse (writer,
1179 if (!_dbus_type_writer_write_basic (&sub,
1183 data_block_restore (block, &saved);
1187 v = SAMPLE_INT32_ALTERNATE;
1188 if (!_dbus_type_writer_write_basic (&sub,
1192 data_block_restore (block, &saved);
1196 if (!_dbus_type_writer_unrecurse (writer, &sub))
1198 data_block_restore (block, &saved);
1206 read_struct_of_int32 (DataBlock *block,
1207 DBusTypeReader *reader)
1212 check_expected_type (reader, DBUS_TYPE_STRUCT);
1214 _dbus_type_reader_recurse (reader, &sub);
1216 check_expected_type (&sub, DBUS_TYPE_INT32);
1218 _dbus_type_reader_read_basic (&sub,
1219 (dbus_int32_t*) &v);
1221 _dbus_assert (v == SAMPLE_INT32);
1223 NEXT_EXPECTING_TRUE (&sub);
1224 check_expected_type (&sub, DBUS_TYPE_INT32);
1226 _dbus_type_reader_read_basic (&sub,
1227 (dbus_int32_t*) &v);
1229 _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1231 NEXT_EXPECTING_FALSE (&sub);
1237 write_struct_of_structs (DataBlock *block,
1238 DBusTypeWriter *writer)
1240 DataBlockState saved;
1243 data_block_save (block, &saved);
1245 if (!_dbus_type_writer_recurse (writer,
1250 if (!write_struct_of_int32 (block, &sub))
1252 data_block_restore (block, &saved);
1255 if (!write_struct_of_int32 (block, &sub))
1257 data_block_restore (block, &saved);
1260 if (!write_struct_of_int32 (block, &sub))
1262 data_block_restore (block, &saved);
1266 if (!_dbus_type_writer_unrecurse (writer, &sub))
1268 data_block_restore (block, &saved);
1276 read_struct_of_structs (DataBlock *block,
1277 DBusTypeReader *reader)
1281 check_expected_type (reader, DBUS_TYPE_STRUCT);
1283 _dbus_type_reader_recurse (reader, &sub);
1285 if (!read_struct_of_int32 (block, &sub))
1288 NEXT_EXPECTING_TRUE (&sub);
1289 if (!read_struct_of_int32 (block, &sub))
1292 NEXT_EXPECTING_TRUE (&sub);
1293 if (!read_struct_of_int32 (block, &sub))
1296 NEXT_EXPECTING_FALSE (&sub);
1302 write_struct_of_structs_of_structs (DataBlock *block,
1303 DBusTypeWriter *writer)
1305 DataBlockState saved;
1308 data_block_save (block, &saved);
1310 if (!_dbus_type_writer_recurse (writer,
1315 if (!write_struct_of_structs (block, &sub))
1317 data_block_restore (block, &saved);
1320 if (!write_struct_of_structs (block, &sub))
1322 data_block_restore (block, &saved);
1326 if (!_dbus_type_writer_unrecurse (writer, &sub))
1328 data_block_restore (block, &saved);
1336 read_struct_of_structs_of_structs (DataBlock *block,
1337 DBusTypeReader *reader)
1341 check_expected_type (reader, DBUS_TYPE_STRUCT);
1343 _dbus_type_reader_recurse (reader, &sub);
1345 if (!read_struct_of_structs (block, &sub))
1348 NEXT_EXPECTING_TRUE (&sub);
1349 if (!read_struct_of_structs (block, &sub))
1352 NEXT_EXPECTING_FALSE (&sub);
1358 write_array_of_int32 (DataBlock *block,
1359 DBusTypeWriter *writer)
1362 DataBlockState saved;
1365 data_block_save (block, &saved);
1367 if (!_dbus_type_writer_recurse_array (writer,
1368 DBUS_TYPE_INT32_AS_STRING,
1372 v = SAMPLE_INT32_ALTERNATE;
1373 if (!_dbus_type_writer_write_basic (&sub,
1377 data_block_restore (block, &saved);
1382 if (!_dbus_type_writer_write_basic (&sub,
1386 data_block_restore (block, &saved);
1391 if (!_dbus_type_writer_write_basic (&sub,
1395 data_block_restore (block, &saved);
1399 if (!_dbus_type_writer_unrecurse (writer, &sub))
1401 data_block_restore (block, &saved);
1409 read_array_of_int32 (DataBlock *block,
1410 DBusTypeReader *reader)
1415 check_expected_type (reader, DBUS_TYPE_ARRAY);
1417 _dbus_type_reader_recurse (reader, &sub);
1419 check_expected_type (&sub, DBUS_TYPE_INT32);
1421 _dbus_type_reader_read_basic (&sub,
1422 (dbus_int32_t*) &v);
1424 _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1426 NEXT_EXPECTING_TRUE (&sub);
1427 check_expected_type (&sub, DBUS_TYPE_INT32);
1429 _dbus_type_reader_read_basic (&sub,
1430 (dbus_int32_t*) &v);
1432 _dbus_assert (v == SAMPLE_INT32);
1434 NEXT_EXPECTING_TRUE (&sub);
1435 check_expected_type (&sub, DBUS_TYPE_INT32);
1437 _dbus_type_reader_read_basic (&sub,
1438 (dbus_int32_t*) &v);
1440 _dbus_assert (v == SAMPLE_INT32);
1442 NEXT_EXPECTING_FALSE (&sub);
1449 write_array_of_int32_empty (DataBlock *block,
1450 DBusTypeWriter *writer)
1452 DataBlockState saved;
1455 data_block_save (block, &saved);
1457 if (!_dbus_type_writer_recurse_array (writer,
1458 DBUS_TYPE_INT32_AS_STRING,
1462 if (!_dbus_type_writer_unrecurse (writer, &sub))
1464 data_block_restore (block, &saved);
1472 read_array_of_int32_empty (DataBlock *block,
1473 DBusTypeReader *reader)
1475 check_expected_type (reader, DBUS_TYPE_ARRAY);
1477 /* We are iterating over values not types. Thus we can't recurse
1480 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1486 write_array_of_array_of_int32 (DataBlock *block,
1487 DBusTypeWriter *writer)
1489 DataBlockState saved;
1492 data_block_save (block, &saved);
1494 if (!_dbus_type_writer_recurse_array (writer,
1495 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1499 if (!write_array_of_int32 (block, &sub))
1501 data_block_restore (block, &saved);
1505 if (!write_array_of_int32 (block, &sub))
1507 data_block_restore (block, &saved);
1511 if (!write_array_of_int32_empty (block, &sub))
1513 data_block_restore (block, &saved);
1517 if (!write_array_of_int32 (block, &sub))
1519 data_block_restore (block, &saved);
1523 if (!_dbus_type_writer_unrecurse (writer, &sub))
1525 data_block_restore (block, &saved);
1533 read_array_of_array_of_int32 (DataBlock *block,
1534 DBusTypeReader *reader)
1538 check_expected_type (reader, DBUS_TYPE_ARRAY);
1540 _dbus_type_reader_recurse (reader, &sub);
1542 if (!read_array_of_int32 (block, &sub))
1545 NEXT_EXPECTING_TRUE (&sub);
1546 if (!read_array_of_int32 (block, &sub))
1549 NEXT_EXPECTING_TRUE (&sub);
1550 if (!read_array_of_int32_empty (block, &sub))
1553 NEXT_EXPECTING_TRUE (&sub);
1554 if (!read_array_of_int32 (block, &sub))
1557 NEXT_EXPECTING_FALSE (&sub);
1564 write_array_of_array_of_int32_empty (DataBlock *block,
1565 DBusTypeWriter *writer)
1567 DataBlockState saved;
1570 data_block_save (block, &saved);
1572 if (!_dbus_type_writer_recurse_array (writer,
1573 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1577 if (!_dbus_type_writer_unrecurse (writer, &sub))
1579 data_block_restore (block, &saved);
1587 read_array_of_array_of_int32_empty (DataBlock *block,
1588 DBusTypeReader *reader)
1590 check_expected_type (reader, DBUS_TYPE_ARRAY);
1592 /* We are iterating over values, not types. Thus
1593 * we can't recurse in here.
1596 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1602 write_array_of_array_of_array_of_int32 (DataBlock *block,
1603 DBusTypeWriter *writer)
1605 DataBlockState saved;
1608 data_block_save (block, &saved);
1610 if (!_dbus_type_writer_recurse_array (writer,
1611 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1615 if (!write_array_of_array_of_int32 (block, &sub))
1617 data_block_restore (block, &saved);
1621 if (!write_array_of_array_of_int32 (block, &sub))
1623 data_block_restore (block, &saved);
1627 if (!write_array_of_array_of_int32_empty (block, &sub))
1629 data_block_restore (block, &saved);
1633 if (!_dbus_type_writer_unrecurse (writer, &sub))
1635 data_block_restore (block, &saved);
1643 read_array_of_array_of_array_of_int32 (DataBlock *block,
1644 DBusTypeReader *reader)
1648 check_expected_type (reader, DBUS_TYPE_ARRAY);
1650 _dbus_type_reader_recurse (reader, &sub);
1652 if (!read_array_of_array_of_int32 (block, &sub))
1655 NEXT_EXPECTING_TRUE (&sub);
1656 if (!read_array_of_array_of_int32 (block, &sub))
1659 NEXT_EXPECTING_TRUE (&sub);
1660 if (!read_array_of_array_of_int32_empty (block, &sub))
1663 NEXT_EXPECTING_FALSE (&sub);
1669 write_struct_of_array_of_int32 (DataBlock *block,
1670 DBusTypeWriter *writer)
1672 DataBlockState saved;
1675 data_block_save (block, &saved);
1677 if (!_dbus_type_writer_recurse (writer,
1682 if (!write_array_of_int32 (block, &sub))
1684 data_block_restore (block, &saved);
1688 if (!write_array_of_int32_empty (block, &sub))
1690 data_block_restore (block, &saved);
1694 if (!_dbus_type_writer_unrecurse (writer, &sub))
1696 data_block_restore (block, &saved);
1704 read_struct_of_array_of_int32 (DataBlock *block,
1705 DBusTypeReader *reader)
1709 check_expected_type (reader, DBUS_TYPE_STRUCT);
1711 _dbus_type_reader_recurse (reader, &sub);
1713 check_expected_type (&sub, DBUS_TYPE_ARRAY);
1715 if (!read_array_of_int32 (block, &sub))
1718 NEXT_EXPECTING_TRUE (&sub);
1719 if (!read_array_of_int32_empty (block, &sub))
1722 NEXT_EXPECTING_FALSE (&sub);
1728 write_struct_of_struct_of_array_of_int32 (DataBlock *block,
1729 DBusTypeWriter *writer)
1731 DataBlockState saved;
1734 data_block_save (block, &saved);
1736 if (!_dbus_type_writer_recurse (writer,
1741 if (!write_struct_of_array_of_int32 (block, &sub))
1743 data_block_restore (block, &saved);
1746 if (!write_struct_of_array_of_int32 (block, &sub))
1748 data_block_restore (block, &saved);
1751 if (!write_struct_of_array_of_int32 (block, &sub))
1753 data_block_restore (block, &saved);
1757 if (!_dbus_type_writer_unrecurse (writer, &sub))
1759 data_block_restore (block, &saved);
1767 read_struct_of_struct_of_array_of_int32 (DataBlock *block,
1768 DBusTypeReader *reader)
1772 check_expected_type (reader, DBUS_TYPE_STRUCT);
1774 _dbus_type_reader_recurse (reader, &sub);
1776 if (!read_struct_of_array_of_int32 (block, &sub))
1779 NEXT_EXPECTING_TRUE (&sub);
1780 if (!read_struct_of_array_of_int32 (block, &sub))
1783 NEXT_EXPECTING_TRUE (&sub);
1784 if (!read_struct_of_array_of_int32 (block, &sub))
1787 NEXT_EXPECTING_FALSE (&sub);
1793 write_array_of_struct_of_int32 (DataBlock *block,
1794 DBusTypeWriter *writer)
1796 DataBlockState saved;
1799 data_block_save (block, &saved);
1801 if (!_dbus_type_writer_recurse_array (writer,
1802 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
1803 DBUS_TYPE_INT32_AS_STRING
1804 DBUS_TYPE_INT32_AS_STRING
1805 DBUS_STRUCT_END_CHAR_AS_STRING,
1809 if (!write_struct_of_int32 (block, &sub))
1811 data_block_restore (block, &saved);
1815 if (!write_struct_of_int32 (block, &sub))
1817 data_block_restore (block, &saved);
1821 if (!write_struct_of_int32 (block, &sub))
1823 data_block_restore (block, &saved);
1827 if (!_dbus_type_writer_unrecurse (writer, &sub))
1829 data_block_restore (block, &saved);
1837 read_array_of_struct_of_int32 (DataBlock *block,
1838 DBusTypeReader *reader)
1842 check_expected_type (reader, DBUS_TYPE_ARRAY);
1844 _dbus_type_reader_recurse (reader, &sub);
1846 check_expected_type (&sub, DBUS_TYPE_STRUCT);
1848 if (!read_struct_of_int32 (block, &sub))
1851 NEXT_EXPECTING_TRUE (&sub);
1853 if (!read_struct_of_int32 (block, &sub))
1856 NEXT_EXPECTING_TRUE (&sub);
1858 if (!read_struct_of_int32 (block, &sub))
1861 NEXT_EXPECTING_FALSE (&sub);
1868 write_array_of_array_of_struct_of_int32 (DataBlock *block,
1869 DBusTypeWriter *writer)
1871 DataBlockState saved;
1874 data_block_save (block, &saved);
1876 if (!_dbus_type_writer_recurse_array (writer,
1877 DBUS_TYPE_ARRAY_AS_STRING
1878 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
1879 DBUS_TYPE_INT32_AS_STRING
1880 DBUS_TYPE_INT32_AS_STRING
1881 DBUS_STRUCT_END_CHAR_AS_STRING,
1885 if (!write_array_of_struct_of_int32 (block, &sub))
1887 data_block_restore (block, &saved);
1891 if (!write_array_of_struct_of_int32 (block, &sub))
1893 data_block_restore (block, &saved);
1897 if (!write_array_of_struct_of_int32 (block, &sub))
1899 data_block_restore (block, &saved);
1903 if (!_dbus_type_writer_unrecurse (writer, &sub))
1905 data_block_restore (block, &saved);
1913 read_array_of_array_of_struct_of_int32 (DataBlock *block,
1914 DBusTypeReader *reader)
1918 check_expected_type (reader, DBUS_TYPE_ARRAY);
1920 _dbus_type_reader_recurse (reader, &sub);
1922 check_expected_type (&sub, DBUS_TYPE_ARRAY);
1924 if (!read_array_of_struct_of_int32 (block, &sub))
1927 NEXT_EXPECTING_TRUE (&sub);
1929 if (!read_array_of_struct_of_int32 (block, &sub))
1932 NEXT_EXPECTING_TRUE (&sub);
1934 if (!read_array_of_struct_of_int32 (block, &sub))
1937 NEXT_EXPECTING_FALSE (&sub);
1943 write_struct_of_array_of_struct_of_int32 (DataBlock *block,
1944 DBusTypeWriter *writer)
1946 DataBlockState saved;
1949 data_block_save (block, &saved);
1951 if (!_dbus_type_writer_recurse (writer,
1956 if (!write_array_of_struct_of_int32 (block, &sub))
1958 data_block_restore (block, &saved);
1961 if (!write_array_of_struct_of_int32 (block, &sub))
1963 data_block_restore (block, &saved);
1966 if (!write_array_of_struct_of_int32 (block, &sub))
1968 data_block_restore (block, &saved);
1972 if (!_dbus_type_writer_unrecurse (writer, &sub))
1974 data_block_restore (block, &saved);
1982 read_struct_of_array_of_struct_of_int32 (DataBlock *block,
1983 DBusTypeReader *reader)
1987 check_expected_type (reader, DBUS_TYPE_STRUCT);
1989 _dbus_type_reader_recurse (reader, &sub);
1991 if (!read_array_of_struct_of_int32 (block, &sub))
1994 NEXT_EXPECTING_TRUE (&sub);
1995 if (!read_array_of_struct_of_int32 (block, &sub))
1998 NEXT_EXPECTING_TRUE (&sub);
1999 if (!read_array_of_struct_of_int32 (block, &sub))
2002 NEXT_EXPECTING_FALSE (&sub);
2008 write_array_of_struct_of_array_of_int32 (DataBlock *block,
2009 DBusTypeWriter *writer)
2011 DataBlockState saved;
2014 data_block_save (block, &saved);
2016 if (!_dbus_type_writer_recurse_array (writer,
2017 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2018 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
2019 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
2020 DBUS_STRUCT_END_CHAR_AS_STRING,
2024 if (!write_struct_of_array_of_int32 (block, &sub))
2026 data_block_restore (block, &saved);
2030 if (!write_struct_of_array_of_int32 (block, &sub))
2032 data_block_restore (block, &saved);
2036 if (!write_struct_of_array_of_int32 (block, &sub))
2038 data_block_restore (block, &saved);
2042 if (!_dbus_type_writer_unrecurse (writer, &sub))
2044 data_block_restore (block, &saved);
2052 read_array_of_struct_of_array_of_int32 (DataBlock *block,
2053 DBusTypeReader *reader)
2057 check_expected_type (reader, DBUS_TYPE_ARRAY);
2059 _dbus_type_reader_recurse (reader, &sub);
2061 check_expected_type (&sub, DBUS_TYPE_STRUCT);
2063 if (!read_struct_of_array_of_int32 (block, &sub))
2066 NEXT_EXPECTING_TRUE (&sub);
2068 if (!read_struct_of_array_of_int32 (block, &sub))
2071 NEXT_EXPECTING_TRUE (&sub);
2073 if (!read_struct_of_array_of_int32 (block, &sub))
2076 NEXT_EXPECTING_FALSE (&sub);
2086 ITEM_STRUCT_OF_INT32,
2087 ITEM_STRUCT_OF_STRUCTS,
2088 ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2090 ITEM_ARRAY_OF_INT32,
2091 ITEM_ARRAY_OF_INT32_EMPTY,
2092 ITEM_ARRAY_OF_ARRAY_OF_INT32,
2093 ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2094 ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2096 ITEM_STRUCT_OF_ARRAY_OF_INT32,
2097 ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2099 ITEM_ARRAY_OF_STRUCT_OF_INT32,
2100 ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2102 ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2103 ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2109 typedef dbus_bool_t (* WriteItemFunc) (DataBlock *block,
2110 DBusTypeWriter *writer);
2111 typedef dbus_bool_t (* ReadItemFunc) (DataBlock *block,
2112 DBusTypeReader *reader);
2118 WriteItemFunc write_item_func;
2119 ReadItemFunc read_item_func;
2122 static CheckMarshalItem items[] = {
2124 ITEM_INT32, write_int32, read_int32 },
2125 { "struct with two int32",
2126 ITEM_STRUCT_OF_INT32, write_struct_of_int32, read_struct_of_int32 },
2127 { "struct with three structs of two int32",
2128 ITEM_STRUCT_OF_STRUCTS, write_struct_of_structs, read_struct_of_structs },
2129 { "struct of two structs of three structs of two int32",
2130 ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2131 write_struct_of_structs_of_structs,
2132 read_struct_of_structs_of_structs },
2134 ITEM_ARRAY_OF_INT32, write_array_of_int32, read_array_of_int32 },
2135 { "empty array of int32",
2136 ITEM_ARRAY_OF_INT32_EMPTY, write_array_of_int32_empty, read_array_of_int32_empty },
2137 { "array of array of int32",
2138 ITEM_ARRAY_OF_ARRAY_OF_INT32,
2139 write_array_of_array_of_int32, read_array_of_array_of_int32 },
2140 { "empty array of array of int32",
2141 ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2142 write_array_of_array_of_int32_empty, read_array_of_array_of_int32_empty },
2143 { "array of array of array of int32",
2144 ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2145 write_array_of_array_of_array_of_int32, read_array_of_array_of_array_of_int32 },
2146 { "struct of array of int32",
2147 ITEM_STRUCT_OF_ARRAY_OF_INT32, write_struct_of_array_of_int32, read_struct_of_array_of_int32 },
2148 { "struct of struct of array of int32",
2149 ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2150 write_struct_of_struct_of_array_of_int32, read_struct_of_struct_of_array_of_int32 },
2151 { "array of struct of int32",
2152 ITEM_ARRAY_OF_STRUCT_OF_INT32, write_array_of_struct_of_int32, read_array_of_struct_of_int32 },
2153 { "array of array of struct of int32",
2154 ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2155 write_array_of_array_of_struct_of_int32, read_array_of_array_of_struct_of_int32 },
2157 { "struct of array of struct of int32",
2158 ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2159 write_struct_of_array_of_struct_of_int32, read_struct_of_array_of_struct_of_int32 },
2160 { "array of struct of array of int32",
2161 ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2162 write_array_of_struct_of_array_of_int32, read_array_of_struct_of_array_of_int32 },
2167 /* Array of items from the above items[]; -1 terminated */
2171 static TestRun runs[] = {
2172 { { ITEM_INVALID } },
2175 { { ITEM_INT32, ITEM_INVALID } },
2176 { { ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2177 { { ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2179 /* STRUCT_OF_INT32 */
2180 { { ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2181 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2182 { { ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2183 { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2184 { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2186 /* STRUCT_OF_STRUCTS */
2187 { { ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2188 { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2189 { { ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2190 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2191 { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2192 { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2194 /* STRUCT_OF_STRUCTS_OF_STRUCTS */
2195 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2196 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2197 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2198 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2199 { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2200 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2202 /* ARRAY_OF_INT32 */
2203 { { ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2204 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2205 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2206 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2207 { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2208 { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2209 { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2210 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2211 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2212 { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2214 /* ARRAY_OF_ARRAY_OF_INT32 */
2215 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2216 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2217 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2218 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2219 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2220 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2221 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2222 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2223 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2224 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2226 /* ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32 */
2227 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2228 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2229 { { 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 } },
2230 { { 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 } },
2231 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2232 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2233 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2234 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2235 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2236 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2238 /* STRUCT_OF_ARRAY_OF_INT32 */
2239 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2240 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2241 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2242 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2243 { { ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2244 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2246 /* STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32 */
2247 { { ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2249 /* ARRAY_OF_STRUCT_OF_INT32 */
2250 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2251 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2252 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2253 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2254 { { ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2255 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2257 /* ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32 */
2258 { { ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2260 /* STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32 */
2261 { { ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2263 /* ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32 */
2264 { { ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2269 perform_one_run (DataBlock *block,
2273 DBusTypeReader reader;
2274 DBusTypeWriter writer;
2276 DataBlockState saved;
2282 _dbus_verbose ("run byteorder %s items ",
2283 byte_order == DBUS_LITTLE_ENDIAN ? "little" : "big");
2285 while (run->items[i] != ITEM_INVALID)
2287 CheckMarshalItem *item = &items[run->items[i]];
2289 _dbus_verbose ("%s ", item->desc);
2292 _dbus_verbose (" = %d items\n", i);
2295 data_block_save (block, &saved);
2297 data_block_init_reader_writer (block,
2302 while (run->items[i] != ITEM_INVALID)
2304 CheckMarshalItem *item = &items[run->items[i]];
2306 _dbus_verbose (">>writing %s\n", item->desc);
2308 if (!(* item->write_item_func) (block, &writer))
2314 while (run->items[i] != ITEM_INVALID)
2316 CheckMarshalItem *item = &items[run->items[i]];
2318 _dbus_verbose (">>data for reading %s\n", item->desc);
2320 _dbus_verbose_bytes_of_string (reader.type_str, 0,
2321 _dbus_string_get_length (reader.type_str));
2322 _dbus_verbose_bytes_of_string (reader.value_str, 0,
2323 _dbus_string_get_length (reader.value_str));
2325 _dbus_verbose (">>reading %s\n", item->desc);
2327 if (!(* item->read_item_func) (block, &reader))
2330 _dbus_type_reader_next (&reader);
2338 data_block_restore (block, &saved);
2343 perform_all_runs (int byte_order,
2352 if (!data_block_init (&block))
2355 if (!_dbus_string_lengthen (&block.signature, initial_offset))
2358 if (!_dbus_string_lengthen (&block.body, initial_offset))
2362 while (i < _DBUS_N_ELEMENTS (runs))
2364 if (!perform_one_run (&block, byte_order, &runs[i]))
2373 data_block_free (&block);
2379 perform_all_items (int byte_order,
2389 if (!data_block_init (&block))
2393 if (!_dbus_string_lengthen (&block.signature, initial_offset))
2396 if (!_dbus_string_lengthen (&block.body, initial_offset))
2399 /* Create a run containing all the items */
2401 while (i < _DBUS_N_ELEMENTS (items))
2403 _dbus_assert (i == items[i].which);
2405 run.items[i] = items[i].which;
2410 run.items[i] = ITEM_INVALID;
2412 if (!perform_one_run (&block, byte_order, &run))
2418 data_block_free (&block);
2424 recursive_marshal_test_iteration (void *data)
2431 if (!perform_all_runs (DBUS_LITTLE_ENDIAN, i))
2433 if (!perform_all_runs (DBUS_BIG_ENDIAN, i))
2435 if (!perform_all_items (DBUS_LITTLE_ENDIAN, i))
2437 if (!perform_all_items (DBUS_BIG_ENDIAN, i))
2446 dbus_bool_t _dbus_marshal_recursive_test (void);
2449 _dbus_marshal_recursive_test (void)
2451 _dbus_test_oom_handling ("recursive marshaling",
2452 recursive_marshal_test_iteration,
2460 main (int argc, char **argv)
2462 _dbus_marshal_recursive_test ();
2468 #endif /* DBUS_BUILD_TESTS */