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;
557 _dbus_type_writer_init (DBusTypeWriter *writer,
559 DBusString *type_str,
561 DBusString *value_str,
564 writer->byte_order = byte_order;
565 writer->type_str = type_str;
566 writer->type_pos = type_pos;
567 writer->value_str = value_str;
568 writer->value_pos = value_pos;
569 writer->container_type = DBUS_TYPE_INVALID;
570 writer->inside_array = FALSE;
572 _dbus_verbose ("writer %p init remaining sig '%s'\n", writer,
573 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
577 _dbus_type_writer_write_basic_no_typecode (DBusTypeWriter *writer,
584 old_value_len = _dbus_string_get_length (writer->value_str);
586 if (!_dbus_marshal_basic_type (writer->value_str,
593 bytes_written = _dbus_string_get_length (writer->value_str) - old_value_len;
595 writer->value_pos += bytes_written;
600 /* If our parent is an array, things are a little bit complicated.
602 * The parent must have a complete element type, such as
603 * "i" or "aai" or "(ii)" or "a(ii)". There can't be
604 * unclosed parens, or an "a" with no following type.
606 * To recurse, the only allowed operation is to recurse into the
607 * first type in the element type. So for "i" you can't recurse, for
608 * "ai" you can recurse into the array, for "(ii)" you can recurse
611 * If you recurse into the array for "ai", then you must specify
612 * "i" for the element type of the array you recurse into.
614 * While inside an array at any level, we need to avoid writing to
615 * type_str, since the type only appears once for the whole array,
616 * it does not appear for each array element.
618 * While inside an array type_pos points to the expected next
619 * typecode, rather than the next place we could write a typecode.
622 writer_recurse_init_and_check (DBusTypeWriter *writer,
626 _dbus_type_writer_init (sub,
633 sub->container_type = container_type;
635 if (writer->inside_array || sub->container_type == DBUS_TYPE_ARRAY)
636 sub->inside_array = TRUE;
638 sub->inside_array = FALSE;
640 #ifndef DBUS_DISABLE_CHECKS
641 if (writer->inside_array)
645 expected = first_type_in_signature (writer->type_str, writer->type_pos);
647 if (expected != sub->container_type)
649 _dbus_warn ("Writing an element of type %s, but the expected type here is %s\n",
650 _dbus_type_to_string (sub->container_type),
651 _dbus_type_to_string (expected));
652 _dbus_assert_not_reached ("bad array element written");
655 #endif /* DBUS_DISABLE_CHECKS */
657 _dbus_verbose (" type writer %p recurse parent type_pos = %d value_pos = %d inside_array = %d container_type = %s remaining sig '%s'\n",
658 writer, writer->type_pos, writer->value_pos, writer->inside_array,
659 _dbus_type_to_string (writer->container_type),
660 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
661 _dbus_verbose (" type writer %p recurse sub type_pos = %d value_pos = %d inside_array = %d container_type = %s\n",
662 sub, sub->type_pos, sub->value_pos,
664 _dbus_type_to_string (sub->container_type));
668 write_or_verify_typecode (DBusTypeWriter *writer,
671 /* A subwriter inside an array will have type_pos pointing to the
672 * expected typecode; a writer not inside an array has type_pos
673 * pointing to the next place to insert a typecode.
675 _dbus_verbose (" type writer %p write_or_verify start type_pos = %d remaining sig '%s'\n",
676 writer, writer->type_pos,
677 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
679 if (writer->inside_array)
681 #ifndef DBUS_DISABLE_CHECKS
685 expected = _dbus_string_get_byte (writer->type_str, writer->type_pos);
687 if (expected != typecode)
689 _dbus_warn ("Array type requires that type %s be written, but %s was written\n",
690 _dbus_type_to_string (expected), _dbus_type_to_string (typecode));
691 _dbus_assert_not_reached ("bad type inserted somewhere inside an array");
694 #endif /* DBUS_DISABLE_CHECKS */
696 /* if immediately inside an array we'd always be appending an element,
697 * so the expected type doesn't change; if inside a struct or something
698 * below an array, we need to move through said struct or something.
700 if (writer->container_type != DBUS_TYPE_ARRAY)
701 writer->type_pos += 1;
705 if (!_dbus_string_insert_byte (writer->type_str,
710 writer->type_pos += 1;
713 _dbus_verbose (" type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
714 writer, writer->type_pos,
715 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
721 _dbus_type_writer_recurse (DBusTypeWriter *writer,
725 writer_recurse_init_and_check (writer, container_type, sub);
727 switch (container_type)
729 case DBUS_TYPE_STRUCT:
731 /* Ensure that we'll be able to add alignment padding and the typecode */
732 if (!_dbus_string_alloc_space (sub->value_str, 8))
735 if (!write_or_verify_typecode (sub, DBUS_STRUCT_BEGIN_CHAR))
736 _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
738 if (!_dbus_string_insert_bytes (sub->value_str,
740 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
742 _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
743 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
746 case DBUS_TYPE_ARRAY:
747 _dbus_assert_not_reached ("use recurse_array() for arrays");
750 _dbus_assert_not_reached ("container_type unhandled");
758 _dbus_type_writer_recurse_array (DBusTypeWriter *writer,
759 const char *element_type,
762 int element_type_len;
763 DBusString element_type_str;
764 dbus_uint32_t value = 0;
769 writer_recurse_init_and_check (writer, DBUS_TYPE_ARRAY, sub);
771 #ifndef DBUS_DISABLE_CHECKS
772 if (writer->container_type == DBUS_TYPE_ARRAY)
774 DBusString parent_elements;
776 _dbus_assert (element_type != NULL);
778 _dbus_string_init_const (&parent_elements,
779 _dbus_string_get_const_data_len (writer->type_str,
780 writer->u.array.element_type_pos + 1,
783 if (!_dbus_string_starts_with_c_str (&parent_elements, element_type))
785 _dbus_warn ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
787 _dbus_assert_not_reached ("incompatible type for child array");
790 #endif /* DBUS_DISABLE_CHECKS */
792 _dbus_string_init_const (&element_type_str, element_type);
793 element_type_len = _dbus_string_get_length (&element_type_str);
795 /* 4 bytes for the array length and 4 bytes possible padding */
796 if (!_dbus_string_alloc_space (sub->value_str, 8))
799 sub->type_pos += 1; /* move to point to the element type, since type_pos
800 * should be the expected type for further writes
802 sub->u.array.element_type_pos = sub->type_pos;
803 sub->u.array.element_type_len = element_type_len;
805 if (!writer->inside_array)
807 /* sub is a toplevel/outermost array so we need to write the type data */
809 /* alloc space for array typecode, element signature, possible 7
812 if (!_dbus_string_alloc_space (writer->type_str, 1 + element_type_len + 7))
815 if (!_dbus_string_insert_byte (writer->type_str,
818 _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
820 if (!_dbus_string_copy (&element_type_str, 0,
821 sub->type_str, sub->u.array.element_type_pos))
822 _dbus_assert_not_reached ("should not have failed to insert array element typecodes");
825 /* Write the length */
826 sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
828 if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
830 _dbus_assert_not_reached ("should not have failed to insert array len");
832 _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
834 /* Write alignment padding for array elements */
835 _dbus_string_init_const (&str, element_type);
836 alignment = element_type_get_alignment (&str, 0);
838 aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
839 if (aligned != sub->value_pos)
841 if (!_dbus_string_insert_bytes (sub->value_str,
843 aligned - sub->value_pos,
845 _dbus_assert_not_reached ("should not have failed to insert alignment padding");
847 sub->value_pos = aligned;
849 sub->u.array.start_pos = sub->value_pos;
851 _dbus_assert (sub->u.array.start_pos == sub->value_pos);
852 _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
854 _dbus_verbose (" type writer %p recurse array done remaining sig '%s'\n", sub,
855 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
861 _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
864 _dbus_assert (sub->type_pos > 0); /* can't be recursed if this fails */
866 _dbus_verbose (" type writer %p unrecurse type_pos = %d value_pos = %d inside_array = %d container_type = %s\n",
867 writer, writer->type_pos, writer->value_pos, writer->inside_array,
868 _dbus_type_to_string (writer->container_type));
869 _dbus_verbose (" type writer %p unrecurse sub type_pos = %d value_pos = %d inside_array = %d container_type = %s\n",
870 sub, sub->type_pos, sub->value_pos,
872 _dbus_type_to_string (sub->container_type));
874 if (sub->container_type == DBUS_TYPE_STRUCT)
876 if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
879 else if (sub->container_type == DBUS_TYPE_ARRAY)
883 /* Set the array length */
884 len = sub->value_pos - sub->u.array.start_pos;
885 _dbus_marshal_set_uint32 (sub->value_str,
887 sub->u.array.len_pos,
889 _dbus_verbose (" filled in sub array len to %u at len_pos %d\n",
890 len, sub->u.array.len_pos);
893 /* Now get type_pos right for the parent writer. Here are the cases:
895 * Cases !writer->inside_array:
896 * (in these cases we want to update to the new insertion point)
898 * - we recursed from STRUCT or INVALID into STRUCT and type_pos
899 * is the new insertion point in all cases
900 * writer->type_pos = sub->type_pos
902 * - we recursed from STRUCT or INVALID into ARRAY, so type_pos in
903 * the child is the array element type, and type_pos in the parent
904 * currently is the child array type but should be set to the
905 * insertion point just after the element type
906 * writer->type_pos = sub->element_type_pos + sub->element_type_len
908 * Cases where writer->inside_array:
909 * (in these cases we want to update to next expected write)
911 * - we recursed from STRUCT into STRUCT somewhere inside an array
912 * element; type_pos in parent is at the child's begin_struct, and
913 * type_pos in the child is at the next field type for the parent
914 * writer->type_pos = sub->type_pos
916 * - we recursed from STRUCT or INVALID into ARRAY somewhere inside
917 * an array element, so type_pos in the parent is at the child's
918 * array typecode, and type_pos in the child is at the array
920 * writer->type_pos = sub->element_type_pos + sub->element_type_len
922 * - we recursed from ARRAY into STRUCT, so type_pos in the
923 * parent is the element type starting with STRUCT,
924 * and type_pos in the child is just after the end_struct code
925 * writer->type_pos should remain as-is
927 * - we recursed from ARRAY into ARRAY, so type_pos in the
928 * parent is the element type starting with child's ARRAY code,
929 * type_pos in the child is the element type of the
931 * writer->type_pos should remain as-is
933 if (writer->container_type == DBUS_TYPE_ARRAY)
935 /* Don't do anything, because sub was an element, and the type
936 * of subsequent elements should be the same
939 else if (sub->container_type == DBUS_TYPE_ARRAY)
941 /* Jump to the next type in the parent's type signature,
942 * which is after our array element type
944 _dbus_assert (writer->container_type != DBUS_TYPE_ARRAY);
945 writer->type_pos = sub->u.array.element_type_pos + sub->u.array.element_type_len;
949 writer->type_pos = sub->type_pos;
952 writer->value_pos = sub->value_pos;
954 _dbus_verbose (" type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
955 writer, writer->type_pos, writer->value_pos,
956 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
962 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
968 /* First ensure that our type realloc will succeed */
969 if (!_dbus_string_alloc_space (writer->type_str, 1))
974 if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
977 if (!write_or_verify_typecode (writer, type))
978 _dbus_assert_not_reached ("failed to write typecode after prealloc");
983 _dbus_verbose (" type writer %p basic type_pos = %d value_pos = %d inside_array = %d\n",
984 writer, writer->type_pos, writer->value_pos, writer->inside_array);
990 _dbus_type_writer_write_array (DBusTypeWriter *writer,
999 /** @} */ /* end of DBusMarshal group */
1001 #ifdef DBUS_BUILD_TESTS
1002 #include "dbus-test.h"
1008 DBusString signature;
1019 data_block_init (DataBlock *block)
1021 if (!_dbus_string_init (&block->signature))
1024 if (!_dbus_string_init (&block->body))
1026 _dbus_string_free (&block->signature);
1034 data_block_free (DataBlock *block)
1036 _dbus_string_free (&block->signature);
1037 _dbus_string_free (&block->body);
1041 data_block_save (DataBlock *block,
1042 DataBlockState *state)
1044 state->saved_sig_len = _dbus_string_get_length (&block->signature);
1045 state->saved_body_len = _dbus_string_get_length (&block->body);
1049 data_block_restore (DataBlock *block,
1050 DataBlockState *state)
1052 /* These set_length should be shortening things so should always work */
1054 if (!_dbus_string_set_length (&block->signature,
1055 state->saved_sig_len))
1056 _dbus_assert_not_reached ("could not restore signature length");
1058 if (!_dbus_string_set_length (&block->body,
1059 state->saved_body_len))
1060 _dbus_assert_not_reached ("could not restore body length");
1064 data_block_init_reader_writer (DataBlock *block,
1066 DBusTypeReader *reader,
1067 DBusTypeWriter *writer)
1069 _dbus_type_reader_init (reader,
1072 _dbus_string_get_length (&block->signature),
1074 _dbus_string_get_length (&block->body));
1076 _dbus_type_writer_init (writer,
1079 _dbus_string_get_length (&block->signature),
1081 _dbus_string_get_length (&block->body));
1084 #define NEXT_EXPECTING_TRUE(reader) do { if (!_dbus_type_reader_next (reader)) \
1086 _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d\n", \
1087 _DBUS_FUNCTION_NAME, __LINE__); \
1088 _dbus_assert_not_reached ("test failed"); \
1092 #define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader)) \
1094 _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d\n", \
1095 _DBUS_FUNCTION_NAME, __LINE__); \
1096 _dbus_assert_not_reached ("test failed"); \
1098 check_expected_type (reader, DBUS_TYPE_INVALID); \
1101 #define SAMPLE_INT32 12345678
1102 #define SAMPLE_INT32_ALTERNATE 53781429
1104 write_int32 (DataBlock *block,
1105 DBusTypeWriter *writer)
1107 dbus_int32_t v = SAMPLE_INT32;
1109 return _dbus_type_writer_write_basic (writer,
1115 real_check_expected_type (DBusTypeReader *reader,
1117 const char *funcname,
1122 t = _dbus_type_reader_get_current_type (reader);
1126 _dbus_warn ("Read type %s while expecting %s at %s line %d\n",
1127 _dbus_type_to_string (t),
1128 _dbus_type_to_string (expected),
1135 #define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__)
1138 read_int32 (DataBlock *block,
1139 DBusTypeReader *reader)
1143 check_expected_type (reader, DBUS_TYPE_INT32);
1145 _dbus_type_reader_read_basic (reader,
1146 (dbus_int32_t*) &v);
1148 _dbus_assert (v == SAMPLE_INT32);
1154 write_struct_of_int32 (DataBlock *block,
1155 DBusTypeWriter *writer)
1158 DataBlockState saved;
1161 data_block_save (block, &saved);
1163 if (!_dbus_type_writer_recurse (writer,
1169 if (!_dbus_type_writer_write_basic (&sub,
1173 data_block_restore (block, &saved);
1177 v = SAMPLE_INT32_ALTERNATE;
1178 if (!_dbus_type_writer_write_basic (&sub,
1182 data_block_restore (block, &saved);
1186 if (!_dbus_type_writer_unrecurse (writer, &sub))
1188 data_block_restore (block, &saved);
1196 read_struct_of_int32 (DataBlock *block,
1197 DBusTypeReader *reader)
1202 check_expected_type (reader, DBUS_TYPE_STRUCT);
1204 _dbus_type_reader_recurse (reader, &sub);
1206 check_expected_type (&sub, DBUS_TYPE_INT32);
1208 _dbus_type_reader_read_basic (&sub,
1209 (dbus_int32_t*) &v);
1211 _dbus_assert (v == SAMPLE_INT32);
1213 NEXT_EXPECTING_TRUE (&sub);
1214 check_expected_type (&sub, DBUS_TYPE_INT32);
1216 _dbus_type_reader_read_basic (&sub,
1217 (dbus_int32_t*) &v);
1219 _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1221 NEXT_EXPECTING_FALSE (&sub);
1227 write_struct_of_structs (DataBlock *block,
1228 DBusTypeWriter *writer)
1230 DataBlockState saved;
1233 data_block_save (block, &saved);
1235 if (!_dbus_type_writer_recurse (writer,
1240 if (!write_struct_of_int32 (block, &sub))
1242 data_block_restore (block, &saved);
1245 if (!write_struct_of_int32 (block, &sub))
1247 data_block_restore (block, &saved);
1250 if (!write_struct_of_int32 (block, &sub))
1252 data_block_restore (block, &saved);
1256 if (!_dbus_type_writer_unrecurse (writer, &sub))
1258 data_block_restore (block, &saved);
1266 read_struct_of_structs (DataBlock *block,
1267 DBusTypeReader *reader)
1271 check_expected_type (reader, DBUS_TYPE_STRUCT);
1273 _dbus_type_reader_recurse (reader, &sub);
1275 if (!read_struct_of_int32 (block, &sub))
1278 NEXT_EXPECTING_TRUE (&sub);
1279 if (!read_struct_of_int32 (block, &sub))
1282 NEXT_EXPECTING_TRUE (&sub);
1283 if (!read_struct_of_int32 (block, &sub))
1286 NEXT_EXPECTING_FALSE (&sub);
1292 write_struct_of_structs_of_structs (DataBlock *block,
1293 DBusTypeWriter *writer)
1295 DataBlockState saved;
1298 data_block_save (block, &saved);
1300 if (!_dbus_type_writer_recurse (writer,
1305 if (!write_struct_of_structs (block, &sub))
1307 data_block_restore (block, &saved);
1310 if (!write_struct_of_structs (block, &sub))
1312 data_block_restore (block, &saved);
1316 if (!_dbus_type_writer_unrecurse (writer, &sub))
1318 data_block_restore (block, &saved);
1326 read_struct_of_structs_of_structs (DataBlock *block,
1327 DBusTypeReader *reader)
1331 check_expected_type (reader, DBUS_TYPE_STRUCT);
1333 _dbus_type_reader_recurse (reader, &sub);
1335 if (!read_struct_of_structs (block, &sub))
1338 NEXT_EXPECTING_TRUE (&sub);
1339 if (!read_struct_of_structs (block, &sub))
1342 NEXT_EXPECTING_FALSE (&sub);
1348 write_array_of_int32 (DataBlock *block,
1349 DBusTypeWriter *writer)
1352 DataBlockState saved;
1355 data_block_save (block, &saved);
1357 if (!_dbus_type_writer_recurse_array (writer,
1358 DBUS_TYPE_INT32_AS_STRING,
1362 v = SAMPLE_INT32_ALTERNATE;
1363 if (!_dbus_type_writer_write_basic (&sub,
1367 data_block_restore (block, &saved);
1372 if (!_dbus_type_writer_write_basic (&sub,
1376 data_block_restore (block, &saved);
1381 if (!_dbus_type_writer_write_basic (&sub,
1385 data_block_restore (block, &saved);
1389 if (!_dbus_type_writer_unrecurse (writer, &sub))
1391 data_block_restore (block, &saved);
1399 read_array_of_int32 (DataBlock *block,
1400 DBusTypeReader *reader)
1405 check_expected_type (reader, DBUS_TYPE_ARRAY);
1407 _dbus_type_reader_recurse (reader, &sub);
1409 check_expected_type (&sub, DBUS_TYPE_INT32);
1411 _dbus_type_reader_read_basic (&sub,
1412 (dbus_int32_t*) &v);
1414 _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1416 NEXT_EXPECTING_TRUE (&sub);
1417 check_expected_type (&sub, DBUS_TYPE_INT32);
1419 _dbus_type_reader_read_basic (&sub,
1420 (dbus_int32_t*) &v);
1422 _dbus_assert (v == SAMPLE_INT32);
1424 NEXT_EXPECTING_TRUE (&sub);
1425 check_expected_type (&sub, DBUS_TYPE_INT32);
1427 _dbus_type_reader_read_basic (&sub,
1428 (dbus_int32_t*) &v);
1430 _dbus_assert (v == SAMPLE_INT32);
1432 NEXT_EXPECTING_FALSE (&sub);
1439 write_array_of_int32_empty (DataBlock *block,
1440 DBusTypeWriter *writer)
1442 DataBlockState saved;
1445 data_block_save (block, &saved);
1447 if (!_dbus_type_writer_recurse_array (writer,
1448 DBUS_TYPE_INT32_AS_STRING,
1452 if (!_dbus_type_writer_unrecurse (writer, &sub))
1454 data_block_restore (block, &saved);
1462 read_array_of_int32_empty (DataBlock *block,
1463 DBusTypeReader *reader)
1465 check_expected_type (reader, DBUS_TYPE_ARRAY);
1467 /* We are iterating over values not types. Thus we can't recurse
1470 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1476 write_array_of_array_of_int32 (DataBlock *block,
1477 DBusTypeWriter *writer)
1479 DataBlockState saved;
1482 data_block_save (block, &saved);
1484 if (!_dbus_type_writer_recurse_array (writer,
1485 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1489 if (!write_array_of_int32 (block, &sub))
1491 data_block_restore (block, &saved);
1495 if (!write_array_of_int32 (block, &sub))
1497 data_block_restore (block, &saved);
1501 if (!write_array_of_int32_empty (block, &sub))
1503 data_block_restore (block, &saved);
1507 if (!write_array_of_int32 (block, &sub))
1509 data_block_restore (block, &saved);
1513 if (!_dbus_type_writer_unrecurse (writer, &sub))
1515 data_block_restore (block, &saved);
1523 read_array_of_array_of_int32 (DataBlock *block,
1524 DBusTypeReader *reader)
1528 check_expected_type (reader, DBUS_TYPE_ARRAY);
1530 _dbus_type_reader_recurse (reader, &sub);
1532 if (!read_array_of_int32 (block, &sub))
1535 NEXT_EXPECTING_TRUE (&sub);
1536 if (!read_array_of_int32 (block, &sub))
1539 NEXT_EXPECTING_TRUE (&sub);
1540 if (!read_array_of_int32_empty (block, &sub))
1543 NEXT_EXPECTING_TRUE (&sub);
1544 if (!read_array_of_int32 (block, &sub))
1547 NEXT_EXPECTING_FALSE (&sub);
1554 write_array_of_array_of_int32_empty (DataBlock *block,
1555 DBusTypeWriter *writer)
1557 DataBlockState saved;
1560 data_block_save (block, &saved);
1562 if (!_dbus_type_writer_recurse_array (writer,
1563 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1567 if (!_dbus_type_writer_unrecurse (writer, &sub))
1569 data_block_restore (block, &saved);
1577 read_array_of_array_of_int32_empty (DataBlock *block,
1578 DBusTypeReader *reader)
1580 check_expected_type (reader, DBUS_TYPE_ARRAY);
1582 /* We are iterating over values, not types. Thus
1583 * we can't recurse in here.
1586 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1592 write_array_of_array_of_array_of_int32 (DataBlock *block,
1593 DBusTypeWriter *writer)
1595 DataBlockState saved;
1598 data_block_save (block, &saved);
1600 if (!_dbus_type_writer_recurse_array (writer,
1601 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1605 if (!write_array_of_array_of_int32 (block, &sub))
1607 data_block_restore (block, &saved);
1611 if (!write_array_of_array_of_int32 (block, &sub))
1613 data_block_restore (block, &saved);
1617 if (!write_array_of_array_of_int32_empty (block, &sub))
1619 data_block_restore (block, &saved);
1623 if (!_dbus_type_writer_unrecurse (writer, &sub))
1625 data_block_restore (block, &saved);
1633 read_array_of_array_of_array_of_int32 (DataBlock *block,
1634 DBusTypeReader *reader)
1638 check_expected_type (reader, DBUS_TYPE_ARRAY);
1640 _dbus_type_reader_recurse (reader, &sub);
1642 if (!read_array_of_array_of_int32 (block, &sub))
1645 NEXT_EXPECTING_TRUE (&sub);
1646 if (!read_array_of_array_of_int32 (block, &sub))
1649 NEXT_EXPECTING_TRUE (&sub);
1650 if (!read_array_of_array_of_int32_empty (block, &sub))
1653 NEXT_EXPECTING_FALSE (&sub);
1659 write_struct_of_array_of_int32 (DataBlock *block,
1660 DBusTypeWriter *writer)
1662 DataBlockState saved;
1665 data_block_save (block, &saved);
1667 if (!_dbus_type_writer_recurse (writer,
1672 if (!write_array_of_int32 (block, &sub))
1674 data_block_restore (block, &saved);
1678 if (!write_array_of_int32_empty (block, &sub))
1680 data_block_restore (block, &saved);
1684 if (!_dbus_type_writer_unrecurse (writer, &sub))
1686 data_block_restore (block, &saved);
1694 read_struct_of_array_of_int32 (DataBlock *block,
1695 DBusTypeReader *reader)
1699 check_expected_type (reader, DBUS_TYPE_STRUCT);
1701 _dbus_type_reader_recurse (reader, &sub);
1703 check_expected_type (&sub, DBUS_TYPE_ARRAY);
1705 if (!read_array_of_int32 (block, &sub))
1708 NEXT_EXPECTING_TRUE (&sub);
1709 if (!read_array_of_int32_empty (block, &sub))
1712 NEXT_EXPECTING_FALSE (&sub);
1718 write_struct_of_struct_of_array_of_int32 (DataBlock *block,
1719 DBusTypeWriter *writer)
1721 DataBlockState saved;
1724 data_block_save (block, &saved);
1726 if (!_dbus_type_writer_recurse (writer,
1731 if (!write_struct_of_array_of_int32 (block, &sub))
1733 data_block_restore (block, &saved);
1736 if (!write_struct_of_array_of_int32 (block, &sub))
1738 data_block_restore (block, &saved);
1741 if (!write_struct_of_array_of_int32 (block, &sub))
1743 data_block_restore (block, &saved);
1747 if (!_dbus_type_writer_unrecurse (writer, &sub))
1749 data_block_restore (block, &saved);
1757 read_struct_of_struct_of_array_of_int32 (DataBlock *block,
1758 DBusTypeReader *reader)
1762 check_expected_type (reader, DBUS_TYPE_STRUCT);
1764 _dbus_type_reader_recurse (reader, &sub);
1766 if (!read_struct_of_array_of_int32 (block, &sub))
1769 NEXT_EXPECTING_TRUE (&sub);
1770 if (!read_struct_of_array_of_int32 (block, &sub))
1773 NEXT_EXPECTING_TRUE (&sub);
1774 if (!read_struct_of_array_of_int32 (block, &sub))
1777 NEXT_EXPECTING_FALSE (&sub);
1783 write_array_of_struct_of_int32 (DataBlock *block,
1784 DBusTypeWriter *writer)
1786 DataBlockState saved;
1789 data_block_save (block, &saved);
1791 if (!_dbus_type_writer_recurse_array (writer,
1792 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
1793 DBUS_TYPE_INT32_AS_STRING
1794 DBUS_TYPE_INT32_AS_STRING
1795 DBUS_STRUCT_END_CHAR_AS_STRING,
1799 if (!write_struct_of_int32 (block, &sub))
1801 data_block_restore (block, &saved);
1805 if (!write_struct_of_int32 (block, &sub))
1807 data_block_restore (block, &saved);
1811 if (!write_struct_of_int32 (block, &sub))
1813 data_block_restore (block, &saved);
1817 if (!_dbus_type_writer_unrecurse (writer, &sub))
1819 data_block_restore (block, &saved);
1827 read_array_of_struct_of_int32 (DataBlock *block,
1828 DBusTypeReader *reader)
1832 check_expected_type (reader, DBUS_TYPE_ARRAY);
1834 _dbus_type_reader_recurse (reader, &sub);
1836 check_expected_type (&sub, DBUS_TYPE_STRUCT);
1838 if (!read_struct_of_int32 (block, &sub))
1841 NEXT_EXPECTING_TRUE (&sub);
1843 if (!read_struct_of_int32 (block, &sub))
1846 NEXT_EXPECTING_TRUE (&sub);
1848 if (!read_struct_of_int32 (block, &sub))
1851 NEXT_EXPECTING_FALSE (&sub);
1858 write_array_of_array_of_struct_of_int32 (DataBlock *block,
1859 DBusTypeWriter *writer)
1861 DataBlockState saved;
1864 data_block_save (block, &saved);
1866 if (!_dbus_type_writer_recurse_array (writer,
1867 DBUS_TYPE_ARRAY_AS_STRING
1868 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
1869 DBUS_TYPE_INT32_AS_STRING
1870 DBUS_TYPE_INT32_AS_STRING
1871 DBUS_STRUCT_END_CHAR_AS_STRING,
1875 if (!write_array_of_struct_of_int32 (block, &sub))
1877 data_block_restore (block, &saved);
1881 if (!write_array_of_struct_of_int32 (block, &sub))
1883 data_block_restore (block, &saved);
1887 if (!write_array_of_struct_of_int32 (block, &sub))
1889 data_block_restore (block, &saved);
1893 if (!_dbus_type_writer_unrecurse (writer, &sub))
1895 data_block_restore (block, &saved);
1903 read_array_of_array_of_struct_of_int32 (DataBlock *block,
1904 DBusTypeReader *reader)
1908 check_expected_type (reader, DBUS_TYPE_ARRAY);
1910 _dbus_type_reader_recurse (reader, &sub);
1912 check_expected_type (&sub, DBUS_TYPE_ARRAY);
1914 if (!read_array_of_struct_of_int32 (block, &sub))
1917 NEXT_EXPECTING_TRUE (&sub);
1919 if (!read_array_of_struct_of_int32 (block, &sub))
1922 NEXT_EXPECTING_TRUE (&sub);
1924 if (!read_array_of_struct_of_int32 (block, &sub))
1927 NEXT_EXPECTING_FALSE (&sub);
1933 write_struct_of_array_of_struct_of_int32 (DataBlock *block,
1934 DBusTypeWriter *writer)
1936 DataBlockState saved;
1939 data_block_save (block, &saved);
1941 if (!_dbus_type_writer_recurse (writer,
1946 if (!write_array_of_struct_of_int32 (block, &sub))
1948 data_block_restore (block, &saved);
1951 if (!write_array_of_struct_of_int32 (block, &sub))
1953 data_block_restore (block, &saved);
1956 if (!write_array_of_struct_of_int32 (block, &sub))
1958 data_block_restore (block, &saved);
1962 if (!_dbus_type_writer_unrecurse (writer, &sub))
1964 data_block_restore (block, &saved);
1972 read_struct_of_array_of_struct_of_int32 (DataBlock *block,
1973 DBusTypeReader *reader)
1977 check_expected_type (reader, DBUS_TYPE_STRUCT);
1979 _dbus_type_reader_recurse (reader, &sub);
1981 if (!read_array_of_struct_of_int32 (block, &sub))
1984 NEXT_EXPECTING_TRUE (&sub);
1985 if (!read_array_of_struct_of_int32 (block, &sub))
1988 NEXT_EXPECTING_TRUE (&sub);
1989 if (!read_array_of_struct_of_int32 (block, &sub))
1992 NEXT_EXPECTING_FALSE (&sub);
1998 write_array_of_struct_of_array_of_int32 (DataBlock *block,
1999 DBusTypeWriter *writer)
2001 DataBlockState saved;
2004 data_block_save (block, &saved);
2006 if (!_dbus_type_writer_recurse_array (writer,
2007 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2008 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
2009 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
2010 DBUS_STRUCT_END_CHAR_AS_STRING,
2014 if (!write_struct_of_array_of_int32 (block, &sub))
2016 data_block_restore (block, &saved);
2020 if (!write_struct_of_array_of_int32 (block, &sub))
2022 data_block_restore (block, &saved);
2026 if (!write_struct_of_array_of_int32 (block, &sub))
2028 data_block_restore (block, &saved);
2032 if (!_dbus_type_writer_unrecurse (writer, &sub))
2034 data_block_restore (block, &saved);
2042 read_array_of_struct_of_array_of_int32 (DataBlock *block,
2043 DBusTypeReader *reader)
2047 check_expected_type (reader, DBUS_TYPE_ARRAY);
2049 _dbus_type_reader_recurse (reader, &sub);
2051 check_expected_type (&sub, DBUS_TYPE_STRUCT);
2053 if (!read_struct_of_array_of_int32 (block, &sub))
2056 NEXT_EXPECTING_TRUE (&sub);
2058 if (!read_struct_of_array_of_int32 (block, &sub))
2061 NEXT_EXPECTING_TRUE (&sub);
2063 if (!read_struct_of_array_of_int32 (block, &sub))
2066 NEXT_EXPECTING_FALSE (&sub);
2076 ITEM_STRUCT_OF_INT32,
2077 ITEM_STRUCT_OF_STRUCTS,
2078 ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2080 ITEM_ARRAY_OF_INT32,
2081 ITEM_ARRAY_OF_INT32_EMPTY,
2082 ITEM_ARRAY_OF_ARRAY_OF_INT32,
2083 ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2084 ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2086 ITEM_STRUCT_OF_ARRAY_OF_INT32,
2087 ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2089 ITEM_ARRAY_OF_STRUCT_OF_INT32,
2090 ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2092 ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2093 ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2099 typedef dbus_bool_t (* WriteItemFunc) (DataBlock *block,
2100 DBusTypeWriter *writer);
2101 typedef dbus_bool_t (* ReadItemFunc) (DataBlock *block,
2102 DBusTypeReader *reader);
2108 WriteItemFunc write_item_func;
2109 ReadItemFunc read_item_func;
2112 static CheckMarshalItem items[] = {
2114 ITEM_INT32, write_int32, read_int32 },
2115 { "struct with two int32",
2116 ITEM_STRUCT_OF_INT32, write_struct_of_int32, read_struct_of_int32 },
2117 { "struct with three structs of two int32",
2118 ITEM_STRUCT_OF_STRUCTS, write_struct_of_structs, read_struct_of_structs },
2119 { "struct of two structs of three structs of two int32",
2120 ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2121 write_struct_of_structs_of_structs,
2122 read_struct_of_structs_of_structs },
2124 ITEM_ARRAY_OF_INT32, write_array_of_int32, read_array_of_int32 },
2125 { "empty array of int32",
2126 ITEM_ARRAY_OF_INT32_EMPTY, write_array_of_int32_empty, read_array_of_int32_empty },
2127 { "array of array of int32",
2128 ITEM_ARRAY_OF_ARRAY_OF_INT32,
2129 write_array_of_array_of_int32, read_array_of_array_of_int32 },
2130 { "empty array of array of int32",
2131 ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2132 write_array_of_array_of_int32_empty, read_array_of_array_of_int32_empty },
2133 { "array of array of array of int32",
2134 ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2135 write_array_of_array_of_array_of_int32, read_array_of_array_of_array_of_int32 },
2136 { "struct of array of int32",
2137 ITEM_STRUCT_OF_ARRAY_OF_INT32, write_struct_of_array_of_int32, read_struct_of_array_of_int32 },
2138 { "struct of struct of array of int32",
2139 ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2140 write_struct_of_struct_of_array_of_int32, read_struct_of_struct_of_array_of_int32 },
2141 { "array of struct of int32",
2142 ITEM_ARRAY_OF_STRUCT_OF_INT32, write_array_of_struct_of_int32, read_array_of_struct_of_int32 },
2143 { "array of array of struct of int32",
2144 ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2145 write_array_of_array_of_struct_of_int32, read_array_of_array_of_struct_of_int32 },
2147 { "struct of array of struct of int32",
2148 ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2149 write_struct_of_array_of_struct_of_int32, read_struct_of_array_of_struct_of_int32 },
2150 { "array of struct of array of int32",
2151 ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2152 write_array_of_struct_of_array_of_int32, read_array_of_struct_of_array_of_int32 },
2157 /* Array of items from the above items[]; -1 terminated */
2161 static TestRun runs[] = {
2162 { { ITEM_INVALID } },
2165 { { ITEM_INT32, ITEM_INVALID } },
2166 { { ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2167 { { ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2169 /* STRUCT_OF_INT32 */
2170 { { ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2171 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2172 { { ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2173 { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2174 { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2176 /* STRUCT_OF_STRUCTS */
2177 { { ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2178 { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2179 { { ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2180 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2181 { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2182 { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2184 /* STRUCT_OF_STRUCTS_OF_STRUCTS */
2185 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2186 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2187 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2188 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2189 { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2190 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2192 /* ARRAY_OF_INT32 */
2193 { { ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2194 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2195 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2196 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2197 { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2198 { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2199 { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2200 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2201 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2202 { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2204 /* ARRAY_OF_ARRAY_OF_INT32 */
2205 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2206 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2207 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2208 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2209 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2210 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2211 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2212 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2213 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2214 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2216 /* ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32 */
2217 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2218 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2219 { { 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 } },
2220 { { 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 } },
2221 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2222 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2223 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2224 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2225 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2226 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2228 /* STRUCT_OF_ARRAY_OF_INT32 */
2229 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2230 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2231 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2232 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2233 { { ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2234 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2236 /* STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32 */
2237 { { ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2239 /* ARRAY_OF_STRUCT_OF_INT32 */
2240 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2241 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2242 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2243 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2244 { { ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2245 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2247 /* ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32 */
2248 { { ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2250 /* STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32 */
2251 { { ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2253 /* ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32 */
2254 { { ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2259 perform_one_run (DataBlock *block,
2263 DBusTypeReader reader;
2264 DBusTypeWriter writer;
2266 DataBlockState saved;
2272 _dbus_verbose ("run byteorder %s items ",
2273 byte_order == DBUS_LITTLE_ENDIAN ? "little" : "big");
2275 while (run->items[i] != ITEM_INVALID)
2277 CheckMarshalItem *item = &items[run->items[i]];
2279 _dbus_verbose ("%s ", item->desc);
2282 _dbus_verbose (" = %d items\n", i);
2285 data_block_save (block, &saved);
2287 data_block_init_reader_writer (block,
2292 while (run->items[i] != ITEM_INVALID)
2294 CheckMarshalItem *item = &items[run->items[i]];
2296 _dbus_verbose (">>writing %s\n", item->desc);
2298 if (!(* item->write_item_func) (block, &writer))
2304 while (run->items[i] != ITEM_INVALID)
2306 CheckMarshalItem *item = &items[run->items[i]];
2308 _dbus_verbose (">>data for reading %s\n", item->desc);
2310 _dbus_verbose_bytes_of_string (reader.type_str, 0,
2311 _dbus_string_get_length (reader.type_str));
2312 _dbus_verbose_bytes_of_string (reader.value_str, 0,
2313 _dbus_string_get_length (reader.value_str));
2315 _dbus_verbose (">>reading %s\n", item->desc);
2317 if (!(* item->read_item_func) (block, &reader))
2320 _dbus_type_reader_next (&reader);
2328 data_block_restore (block, &saved);
2333 perform_all_runs (int byte_order,
2342 if (!data_block_init (&block))
2345 if (!_dbus_string_lengthen (&block.signature, initial_offset))
2348 if (!_dbus_string_lengthen (&block.body, initial_offset))
2352 while (i < _DBUS_N_ELEMENTS (runs))
2354 if (!perform_one_run (&block, byte_order, &runs[i]))
2363 data_block_free (&block);
2369 perform_all_items (int byte_order,
2379 if (!data_block_init (&block))
2383 if (!_dbus_string_lengthen (&block.signature, initial_offset))
2386 if (!_dbus_string_lengthen (&block.body, initial_offset))
2389 /* Create a run containing all the items */
2391 while (i < _DBUS_N_ELEMENTS (items))
2393 _dbus_assert (i == items[i].which);
2395 run.items[i] = items[i].which;
2400 run.items[i] = ITEM_INVALID;
2402 if (!perform_one_run (&block, byte_order, &run))
2408 data_block_free (&block);
2414 recursive_marshal_test_iteration (void *data)
2421 if (!perform_all_runs (DBUS_LITTLE_ENDIAN, i))
2423 if (!perform_all_runs (DBUS_BIG_ENDIAN, i))
2425 if (!perform_all_items (DBUS_LITTLE_ENDIAN, i))
2427 if (!perform_all_items (DBUS_BIG_ENDIAN, i))
2436 dbus_bool_t _dbus_marshal_recursive_test (void);
2439 _dbus_marshal_recursive_test (void)
2441 _dbus_test_oom_handling ("recursive marshaling",
2442 recursive_marshal_test_iteration,
2450 main (int argc, char **argv)
2452 _dbus_marshal_recursive_test ();
2458 #endif /* DBUS_BUILD_TESTS */