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 variant_reader_recurse (DBusTypeReader *sub,
150 DBusTypeReader *parent)
154 _dbus_assert (!_dbus_type_reader_array_is_empty (parent));
156 base_reader_recurse (sub, parent);
158 /* Variant is 1 byte sig length (without nul), signature with nul,
159 * padding to 8-boundary, then values
162 sig_len = _dbus_string_get_byte (sub->value_str, sub->value_pos);
164 sub->type_str = sub->value_str;
165 sub->type_pos = sub->value_pos + 1;
167 sub->value_pos = sub->type_pos + sig_len + 1;
169 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
171 _dbus_verbose (" type reader %p variant containing '%s'\n",
173 _dbus_string_get_const_data_len (sub->type_str,
178 base_reader_get_current_type (DBusTypeReader *reader)
182 t = first_type_in_signature (reader->type_str,
189 struct_reader_get_current_type (DBusTypeReader *reader)
193 if (reader->u.strct.finished)
194 t = DBUS_TYPE_INVALID;
196 t = first_type_in_signature (reader->type_str,
203 array_reader_get_current_type (DBusTypeReader *reader)
208 /* return the array element type if elements remain, and
209 * TYPE_INVALID otherwise
212 end_pos = reader->u.array.start_pos + reader->u.array.len;
214 _dbus_assert (reader->value_pos <= end_pos);
215 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
217 if (reader->value_pos < end_pos)
218 t = reader->u.array.element_type;
220 t = DBUS_TYPE_INVALID;
226 skip_one_complete_type (const DBusString *type_str,
229 while (_dbus_string_get_byte (type_str, *type_pos) == DBUS_TYPE_ARRAY)
232 if (_dbus_string_get_byte (type_str, *type_pos) == DBUS_STRUCT_BEGIN_CHAR)
239 switch (_dbus_string_get_byte (type_str, *type_pos))
241 case DBUS_STRUCT_BEGIN_CHAR:
244 case DBUS_STRUCT_END_CHAR:
247 case DBUS_TYPE_INVALID:
248 _dbus_assert_not_reached ("unbalanced parens in signature");
259 skip_array_values (int element_type,
260 const DBusString *value_str,
264 dbus_uint32_t array_len;
268 pos = _DBUS_ALIGN_VALUE (*value_pos, 4);
270 _dbus_demarshal_basic_type (value_str,
276 alignment = _dbus_type_get_alignment (element_type);
278 pos = _DBUS_ALIGN_VALUE (pos, alignment);
280 *value_pos = pos + array_len;
284 base_reader_next (DBusTypeReader *reader,
287 switch (current_type)
289 case DBUS_TYPE_STRUCT:
290 /* Scan forward over the entire container contents */
294 /* Recurse into the struct */
295 _dbus_type_reader_recurse (reader, &sub);
297 /* Skip everything in this subreader */
298 while (_dbus_type_reader_next (&sub))
303 /* Now we are at the end of this container */
304 reader->type_pos = sub.type_pos;
305 reader->value_pos = sub.value_pos;
309 case DBUS_TYPE_ARRAY:
311 skip_array_values (first_type_in_signature (reader->type_str,
312 reader->type_pos + 1),
313 reader->value_str, &reader->value_pos, reader->byte_order);
314 skip_one_complete_type (reader->type_str, &reader->type_pos);
319 _dbus_marshal_skip_basic_type (reader->value_str,
320 current_type, reader->byte_order,
322 reader->type_pos += 1;
328 struct_reader_next (DBusTypeReader *reader,
333 base_reader_next (reader, current_type);
335 /* for STRUCT containers we return FALSE at the end of the struct,
336 * for INVALID we return FALSE at the end of the signature.
337 * In both cases we arrange for get_current_type() to return INVALID
338 * which is defined to happen iff we're at the end (no more next())
340 t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
341 if (t == DBUS_STRUCT_END_CHAR)
343 reader->type_pos += 1;
344 reader->u.strct.finished = TRUE;
349 array_reader_next (DBusTypeReader *reader,
352 /* Skip one array element */
355 end_pos = reader->u.array.start_pos + reader->u.array.len;
357 _dbus_assert (reader->value_pos < end_pos);
358 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
360 if (reader->u.array.element_type == DBUS_TYPE_STRUCT)
364 /* Recurse into the struct */
365 _dbus_type_reader_recurse (reader, &sub);
367 /* Skip everything in this element */
368 while (_dbus_type_reader_next (&sub))
373 /* Now we are at the end of this element */
374 reader->value_pos = sub.value_pos;
376 else if (reader->u.array.element_type == DBUS_TYPE_ARRAY)
378 skip_array_values (first_type_in_signature (reader->type_str,
379 reader->type_pos + 1),
380 reader->value_str, &reader->value_pos, reader->byte_order);
384 _dbus_marshal_skip_basic_type (reader->value_str,
385 current_type, reader->byte_order,
389 _dbus_assert (reader->value_pos <= end_pos);
391 if (reader->value_pos == end_pos)
393 skip_one_complete_type (reader->type_str,
398 static const DBusTypeReaderClass body_reader_class = {
400 NULL, /* body is always toplevel, so doesn't get recursed into */
401 base_reader_get_current_type,
405 static const DBusTypeReaderClass struct_reader_class = {
407 struct_reader_recurse,
408 struct_reader_get_current_type,
412 static const DBusTypeReaderClass array_reader_class = {
414 array_reader_recurse,
415 array_reader_get_current_type,
419 static const DBusTypeReaderClass variant_reader_class = {
421 variant_reader_recurse,
422 base_reader_get_current_type,
427 _dbus_type_reader_init (DBusTypeReader *reader,
429 const DBusString *type_str,
431 const DBusString *value_str,
434 reader->klass = &body_reader_class;
436 reader_init (reader, byte_order, type_str, type_pos,
437 value_str, value_pos);
439 _dbus_verbose (" type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
440 reader, reader->type_pos, reader->value_pos,
441 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
445 _dbus_type_reader_get_current_type (DBusTypeReader *reader)
449 t = (* reader->klass->get_current_type) (reader);
451 _dbus_assert (t != DBUS_STRUCT_END_CHAR);
452 _dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR);
455 _dbus_verbose (" type reader %p current type_pos = %d type = %s\n",
456 reader, reader->type_pos,
457 _dbus_type_to_string (t));
464 _dbus_type_reader_array_is_empty (DBusTypeReader *reader)
466 dbus_uint32_t array_len;
469 _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY,
472 len_pos = _DBUS_ALIGN_VALUE (reader->value_pos, 4);
474 _dbus_demarshal_basic_type (reader->value_str,
480 return array_len == 0;
484 _dbus_type_reader_read_basic (DBusTypeReader *reader,
490 t = _dbus_type_reader_get_current_type (reader);
492 next = reader->value_pos;
493 _dbus_demarshal_basic_type (reader->value_str,
499 _dbus_verbose (" type reader %p read basic type_pos = %d value_pos = %d next = %d remaining sig '%s'\n",
500 reader, reader->type_pos, reader->value_pos, next,
501 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
505 _dbus_type_reader_read_array_of_basic (DBusTypeReader *reader,
515 * Initialize a new reader pointing to the first type and
516 * corresponding value that's a child of the current container. It's
517 * an error to call this if the current type is a non-container.
519 * Note that DBusTypeReader traverses values, not types. So if you
520 * have an empty array of array of int, you can't recurse into it. You
521 * can only recurse into each element.
523 * @param reader the reader
524 * @param sub a reader to init pointing to the first child
527 _dbus_type_reader_recurse (DBusTypeReader *reader,
532 t = first_type_in_signature (reader->type_str, reader->type_pos);
536 case DBUS_TYPE_STRUCT:
537 sub->klass = &struct_reader_class;
539 case DBUS_TYPE_ARRAY:
540 sub->klass = &array_reader_class;
542 case DBUS_TYPE_VARIANT:
543 sub->klass = &variant_reader_class;
546 _dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t));
547 #ifndef DBUS_DISABLE_CHECKS
548 if (t == DBUS_TYPE_INVALID)
549 _dbus_warn ("You can't recurse into an empty array or off the end of a message body\n");
550 #endif /* DBUS_DISABLE_CHECKS */
552 _dbus_assert_not_reached ("don't yet handle recursing into this type");
555 (* sub->klass->recurse) (sub, reader);
557 _dbus_verbose (" type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
558 sub, sub->type_pos, sub->value_pos,
559 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
563 * Skip to the next value on this "level". e.g. the next field in a
564 * struct, the next value in an array, the next key or value in a
565 * dict. Returns FALSE at the end of the current container.
567 * @param reader the reader
568 * @returns FALSE if nothing more to read at or below this level
571 _dbus_type_reader_next (DBusTypeReader *reader)
575 t = _dbus_type_reader_get_current_type (reader);
577 _dbus_verbose (" type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
578 reader, reader->type_pos, reader->value_pos,
579 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
580 _dbus_type_to_string (t));
582 if (t == DBUS_TYPE_INVALID)
585 (* reader->klass->next) (reader, t);
587 _dbus_verbose (" type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
588 reader, reader->type_pos, reader->value_pos,
589 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
590 _dbus_type_to_string (_dbus_type_reader_get_current_type (reader)));
592 return _dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID;
606 _dbus_type_writer_init (DBusTypeWriter *writer,
608 DBusString *type_str,
610 DBusString *value_str,
613 writer->byte_order = byte_order;
614 writer->type_str = type_str;
615 writer->type_pos = type_pos;
616 writer->value_str = value_str;
617 writer->value_pos = value_pos;
618 writer->container_type = DBUS_TYPE_INVALID;
619 writer->type_pos_is_expectation = FALSE;
621 _dbus_verbose ("writer %p init remaining sig '%s'\n", writer,
622 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
626 _dbus_type_writer_write_basic_no_typecode (DBusTypeWriter *writer,
633 old_value_len = _dbus_string_get_length (writer->value_str);
635 if (!_dbus_marshal_basic_type (writer->value_str,
642 bytes_written = _dbus_string_get_length (writer->value_str) - old_value_len;
644 writer->value_pos += bytes_written;
649 /* If our parent is an array, things are a little bit complicated.
651 * The parent must have a complete element type, such as
652 * "i" or "aai" or "(ii)" or "a(ii)". There can't be
653 * unclosed parens, or an "a" with no following type.
655 * To recurse, the only allowed operation is to recurse into the
656 * first type in the element type. So for "i" you can't recurse, for
657 * "ai" you can recurse into the array, for "(ii)" you can recurse
660 * If you recurse into the array for "ai", then you must specify
661 * "i" for the element type of the array you recurse into.
663 * While inside an array at any level, we need to avoid writing to
664 * type_str, since the type only appears once for the whole array,
665 * it does not appear for each array element.
667 * While inside an array type_pos points to the expected next
668 * typecode, rather than the next place we could write a typecode.
671 writer_recurse_init_and_check (DBusTypeWriter *writer,
675 _dbus_type_writer_init (sub,
682 sub->container_type = container_type;
684 if (writer->type_pos_is_expectation ||
685 (sub->container_type == DBUS_TYPE_ARRAY || sub->container_type == DBUS_TYPE_VARIANT))
686 sub->type_pos_is_expectation = TRUE;
688 sub->type_pos_is_expectation = FALSE;
690 #ifndef DBUS_DISABLE_CHECKS
691 if (writer->type_pos_is_expectation)
695 expected = first_type_in_signature (writer->type_str, writer->type_pos);
697 if (expected != sub->container_type)
699 _dbus_warn ("Writing an element of type %s, but the expected type here is %s\n",
700 _dbus_type_to_string (sub->container_type),
701 _dbus_type_to_string (expected));
702 _dbus_assert_not_reached ("bad array element or variant content written");
705 #endif /* DBUS_DISABLE_CHECKS */
707 _dbus_verbose (" type writer %p recurse parent type_pos = %d value_pos = %d is_expectation = %d container_type = %s remaining sig '%s'\n",
708 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
709 _dbus_type_to_string (writer->container_type),
710 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
711 _dbus_verbose (" type writer %p recurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
712 sub, sub->type_pos, sub->value_pos,
713 sub->type_pos_is_expectation,
714 _dbus_type_to_string (sub->container_type));
718 write_or_verify_typecode (DBusTypeWriter *writer,
721 /* A subwriter inside an array or variant will have type_pos
722 * pointing to the expected typecode; a writer not inside an array
723 * or variant has type_pos pointing to the next place to insert a
726 _dbus_verbose (" type writer %p write_or_verify start type_pos = %d remaining sig '%s'\n",
727 writer, writer->type_pos,
728 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
730 if (writer->type_pos_is_expectation)
732 #ifndef DBUS_DISABLE_CHECKS
736 expected = _dbus_string_get_byte (writer->type_str, writer->type_pos);
738 if (expected != typecode)
740 _dbus_warn ("Array or Variant type requires that type %s be written, but %s was written\n",
741 _dbus_type_to_string (expected), _dbus_type_to_string (typecode));
742 _dbus_assert_not_reached ("bad type inserted somewhere inside an array or variant");
745 #endif /* DBUS_DISABLE_CHECKS */
747 /* if immediately inside an array we'd always be appending an element,
748 * so the expected type doesn't change; if inside a struct or something
749 * below an array, we need to move through said struct or something.
751 if (writer->container_type != DBUS_TYPE_ARRAY)
752 writer->type_pos += 1;
756 if (!_dbus_string_insert_byte (writer->type_str,
761 writer->type_pos += 1;
764 _dbus_verbose (" type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
765 writer, writer->type_pos,
766 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
772 _dbus_type_writer_recurse_struct (DBusTypeWriter *writer,
775 writer_recurse_init_and_check (writer, DBUS_TYPE_STRUCT, sub);
777 /* Ensure that we'll be able to add alignment padding and the typecode */
778 if (!_dbus_string_alloc_space (sub->value_str, 8))
781 if (!write_or_verify_typecode (sub, DBUS_STRUCT_BEGIN_CHAR))
782 _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
784 if (!_dbus_string_insert_bytes (sub->value_str,
786 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
788 _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
789 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
795 _dbus_type_writer_recurse_array (DBusTypeWriter *writer,
796 const char *element_type,
799 int element_type_len;
800 DBusString element_type_str;
801 dbus_uint32_t value = 0;
806 writer_recurse_init_and_check (writer, DBUS_TYPE_ARRAY, sub);
808 #ifndef DBUS_DISABLE_CHECKS
809 if (writer->container_type == DBUS_TYPE_ARRAY)
811 DBusString parent_elements;
813 _dbus_assert (element_type != NULL);
815 _dbus_string_init_const (&parent_elements,
816 _dbus_string_get_const_data_len (writer->type_str,
817 writer->u.array.element_type_pos + 1,
820 if (!_dbus_string_starts_with_c_str (&parent_elements, element_type))
822 _dbus_warn ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
824 _dbus_assert_not_reached ("incompatible type for child array");
827 #endif /* DBUS_DISABLE_CHECKS */
829 _dbus_string_init_const (&element_type_str, element_type);
830 element_type_len = _dbus_string_get_length (&element_type_str);
832 /* 4 bytes for the array length and 4 bytes possible padding */
833 if (!_dbus_string_alloc_space (sub->value_str, 8))
836 sub->type_pos += 1; /* move to point to the element type, since type_pos
837 * should be the expected type for further writes
839 sub->u.array.element_type_pos = sub->type_pos;
841 if (!writer->type_pos_is_expectation)
843 /* sub is a toplevel/outermost array so we need to write the type data */
845 /* alloc space for array typecode, element signature, possible 7
848 if (!_dbus_string_alloc_space (writer->type_str, 1 + element_type_len + 7))
851 if (!_dbus_string_insert_byte (writer->type_str,
854 _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
856 if (!_dbus_string_copy (&element_type_str, 0,
857 sub->type_str, sub->u.array.element_type_pos))
858 _dbus_assert_not_reached ("should not have failed to insert array element typecodes");
861 /* If the parent is an array, we hold type_pos pointing at the array element type;
862 * otherwise advance it to reflect the array value we just recursed into
864 if (writer->container_type != DBUS_TYPE_ARRAY)
865 writer->type_pos += 1 + element_type_len;
867 _dbus_assert (writer->type_pos_is_expectation); /* because it's an array */
869 /* Write the length */
870 sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
872 if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
874 _dbus_assert_not_reached ("should not have failed to insert array len");
876 _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
878 /* Write alignment padding for array elements */
879 _dbus_string_init_const (&str, element_type);
880 alignment = element_type_get_alignment (&str, 0);
882 aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
883 if (aligned != sub->value_pos)
885 if (!_dbus_string_insert_bytes (sub->value_str,
887 aligned - sub->value_pos,
889 _dbus_assert_not_reached ("should not have failed to insert alignment padding");
891 sub->value_pos = aligned;
893 sub->u.array.start_pos = sub->value_pos;
895 _dbus_assert (sub->u.array.start_pos == sub->value_pos);
896 _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
898 _dbus_verbose (" type writer %p recurse array done remaining sig '%s'\n", sub,
899 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
904 /* Variant value will normally have:
905 * 1 byte signature length not including nul
906 * signature typecodes (nul terminated)
907 * padding to 8-boundary
908 * body according to signature
910 * The signature string can only have a single type
911 * in it but that type may be complex/recursive.
913 * So a typical variant type with the integer 3 will have these
915 * 0x1 'i' '\0' [padding to 8-boundary] 0x0 0x0 0x0 0x3
917 * For an array of 4-byte types stuffed into variants, the padding to
918 * 8-boundary is only the 1 byte that is required for the 4-boundary
919 * anyhow for all array elements after the first one. And for single
920 * variants in isolation, wasting a few bytes is hardly a big deal.
922 * The main world of hurt for writing out a variant is that the type
923 * string is the same string as the value string. Which means
924 * inserting to the type string will move the value_pos; and it means
925 * that inserting to the type string could break type alignment.
927 * This type alignment issue is why the body of the variant is always
928 * 8-aligned. Then we know that re-8-aligning the start of the body
929 * will always correctly align the full contents of the variant type.
932 _dbus_type_writer_recurse_variant (DBusTypeWriter *writer,
933 const char *contained_type,
936 int contained_type_len;
937 DBusString contained_type_str;
939 writer_recurse_init_and_check (writer, DBUS_TYPE_VARIANT, sub);
941 _dbus_string_init_const (&contained_type_str, contained_type);
943 contained_type_len = _dbus_string_get_length (&contained_type_str);
945 /* Allocate space for the worst case, which is 1 byte sig
946 * length, nul byte at end of sig, and 7 bytes padding to
949 if (!_dbus_string_alloc_space (sub->value_str, contained_type_len + 9))
952 /* write VARIANT typecode to the parent's type string */
953 if (!write_or_verify_typecode (sub, DBUS_TYPE_VARIANT))
956 if (!_dbus_string_insert_byte (sub->value_str,
959 _dbus_assert_not_reached ("should not have failed to insert variant type sig len");
963 /* Here we switch over to the expected type sig we're about to write */
964 sub->type_str = sub->value_str;
965 sub->type_pos = sub->value_pos;
967 if (!_dbus_string_copy (&contained_type_str, 0,
968 sub->value_str, sub->value_pos))
969 _dbus_assert_not_reached ("should not have failed to insert variant type sig");
971 sub->value_pos += contained_type_len;
973 if (!_dbus_string_insert_byte (sub->value_str,
976 _dbus_assert_not_reached ("should not have failed to insert variant type nul termination");
980 if (!_dbus_string_insert_bytes (sub->value_str,
982 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
984 _dbus_assert_not_reached ("should not have failed to insert alignment padding for variant body");
985 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
991 _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
994 _dbus_assert (sub->type_pos > 0); /* can't be recursed if this fails */
996 /* type_pos_is_expectation never gets unset once set, or we'd get all hosed */
997 _dbus_assert (!writer->type_pos_is_expectation ||
998 (writer->type_pos_is_expectation && sub->type_pos_is_expectation));
1000 _dbus_verbose (" type writer %p unrecurse type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
1001 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
1002 _dbus_type_to_string (writer->container_type));
1003 _dbus_verbose (" type writer %p unrecurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
1004 sub, sub->type_pos, sub->value_pos,
1005 sub->type_pos_is_expectation,
1006 _dbus_type_to_string (sub->container_type));
1008 if (sub->container_type == DBUS_TYPE_STRUCT)
1010 if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
1013 else if (sub->container_type == DBUS_TYPE_ARRAY)
1017 /* Set the array length */
1018 len = sub->value_pos - sub->u.array.start_pos;
1019 _dbus_marshal_set_uint32 (sub->value_str,
1021 sub->u.array.len_pos,
1023 _dbus_verbose (" filled in sub array len to %u at len_pos %d\n",
1024 len, sub->u.array.len_pos);
1027 /* Now get type_pos right for the parent writer. Here are the cases:
1029 * Cases !writer->type_pos_is_expectation:
1030 * (in these cases we want to update to the new insertion point)
1032 * - if we recursed into a STRUCT then we didn't know in advance
1033 * what the types in the struct would be; so we have to fill in
1034 * that information now.
1035 * writer->type_pos = sub->type_pos
1037 * - if we recursed into anything else, we knew the full array
1038 * type, or knew the single typecode marking VARIANT, so
1039 * writer->type_pos is already correct.
1040 * writer->type_pos should remain as-is
1042 * - note that the parent is never an ARRAY or VARIANT, if it were
1043 * then type_pos_is_expectation would be TRUE. The parent
1044 * is thus known to be a toplevel or STRUCT.
1046 * Cases where writer->type_pos_is_expectation:
1047 * (in these cases we want to update to next expected type to write)
1049 * - we recursed from STRUCT into STRUCT and we didn't increment
1050 * type_pos in the parent just to stay consistent with the
1051 * !writer->type_pos_is_expectation case (though we could
1052 * special-case this in recurse_struct instead if we wanted)
1053 * writer->type_pos = sub->type_pos
1055 * - we recursed from STRUCT into ARRAY or VARIANT and type_pos
1056 * for parent should have been incremented already
1057 * writer->type_pos should remain as-is
1059 * - we recursed from ARRAY into a sub-element, so type_pos in the
1060 * parent is the element type and should remain the element type
1061 * for the benefit of the next child element
1062 * writer->type_pos should remain as-is
1064 * - we recursed from VARIANT into its value, so type_pos in the
1065 * parent makes no difference since there's only one value
1066 * and we just finished writing it and won't use type_pos again
1067 * writer->type_pos should remain as-is
1069 if (sub->container_type == DBUS_TYPE_STRUCT &&
1070 (writer->container_type == DBUS_TYPE_STRUCT ||
1071 writer->container_type == DBUS_TYPE_INVALID))
1073 /* Advance the parent to the next struct field */
1074 writer->type_pos = sub->type_pos;
1077 writer->value_pos = sub->value_pos;
1079 _dbus_verbose (" type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
1080 writer, writer->type_pos, writer->value_pos,
1081 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
1087 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
1093 /* First ensure that our type realloc will succeed */
1094 if (!_dbus_string_alloc_space (writer->type_str, 1))
1099 if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
1102 if (!write_or_verify_typecode (writer, type))
1103 _dbus_assert_not_reached ("failed to write typecode after prealloc");
1108 _dbus_verbose (" type writer %p basic type_pos = %d value_pos = %d is_expectation = %d\n",
1109 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation);
1115 _dbus_type_writer_write_array (DBusTypeWriter *writer,
1124 /** @} */ /* end of DBusMarshal group */
1126 #ifdef DBUS_BUILD_TESTS
1127 #include "dbus-test.h"
1133 DBusString signature;
1144 data_block_init (DataBlock *block)
1146 if (!_dbus_string_init (&block->signature))
1149 if (!_dbus_string_init (&block->body))
1151 _dbus_string_free (&block->signature);
1159 data_block_free (DataBlock *block)
1161 _dbus_string_free (&block->signature);
1162 _dbus_string_free (&block->body);
1166 data_block_save (DataBlock *block,
1167 DataBlockState *state)
1169 state->saved_sig_len = _dbus_string_get_length (&block->signature);
1170 state->saved_body_len = _dbus_string_get_length (&block->body);
1174 data_block_restore (DataBlock *block,
1175 DataBlockState *state)
1177 /* These set_length should be shortening things so should always work */
1179 if (!_dbus_string_set_length (&block->signature,
1180 state->saved_sig_len))
1181 _dbus_assert_not_reached ("could not restore signature length");
1183 if (!_dbus_string_set_length (&block->body,
1184 state->saved_body_len))
1185 _dbus_assert_not_reached ("could not restore body length");
1189 data_block_init_reader_writer (DataBlock *block,
1191 DBusTypeReader *reader,
1192 DBusTypeWriter *writer)
1194 _dbus_type_reader_init (reader,
1197 _dbus_string_get_length (&block->signature),
1199 _dbus_string_get_length (&block->body));
1201 _dbus_type_writer_init (writer,
1204 _dbus_string_get_length (&block->signature),
1206 _dbus_string_get_length (&block->body));
1209 #define NEXT_EXPECTING_TRUE(reader) do { if (!_dbus_type_reader_next (reader)) \
1211 _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d\n", \
1212 _DBUS_FUNCTION_NAME, __LINE__); \
1213 _dbus_assert_not_reached ("test failed"); \
1217 #define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader)) \
1219 _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d\n", \
1220 _DBUS_FUNCTION_NAME, __LINE__); \
1221 _dbus_assert_not_reached ("test failed"); \
1223 check_expected_type (reader, DBUS_TYPE_INVALID); \
1226 #define SAMPLE_INT32 12345678
1227 #define SAMPLE_INT32_ALTERNATE 53781429
1229 write_int32 (DataBlock *block,
1230 DBusTypeWriter *writer)
1232 dbus_int32_t v = SAMPLE_INT32;
1234 return _dbus_type_writer_write_basic (writer,
1240 real_check_expected_type (DBusTypeReader *reader,
1242 const char *funcname,
1247 t = _dbus_type_reader_get_current_type (reader);
1251 _dbus_warn ("Read type %s while expecting %s at %s line %d\n",
1252 _dbus_type_to_string (t),
1253 _dbus_type_to_string (expected),
1260 #define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__)
1263 read_int32 (DataBlock *block,
1264 DBusTypeReader *reader)
1268 check_expected_type (reader, DBUS_TYPE_INT32);
1270 _dbus_type_reader_read_basic (reader,
1271 (dbus_int32_t*) &v);
1273 _dbus_assert (v == SAMPLE_INT32);
1279 write_struct_of_int32 (DataBlock *block,
1280 DBusTypeWriter *writer)
1283 DataBlockState saved;
1286 data_block_save (block, &saved);
1288 if (!_dbus_type_writer_recurse_struct (writer,
1293 if (!_dbus_type_writer_write_basic (&sub,
1297 data_block_restore (block, &saved);
1301 v = SAMPLE_INT32_ALTERNATE;
1302 if (!_dbus_type_writer_write_basic (&sub,
1306 data_block_restore (block, &saved);
1310 if (!_dbus_type_writer_unrecurse (writer, &sub))
1312 data_block_restore (block, &saved);
1320 read_struct_of_int32 (DataBlock *block,
1321 DBusTypeReader *reader)
1326 check_expected_type (reader, DBUS_TYPE_STRUCT);
1328 _dbus_type_reader_recurse (reader, &sub);
1330 check_expected_type (&sub, DBUS_TYPE_INT32);
1332 _dbus_type_reader_read_basic (&sub,
1333 (dbus_int32_t*) &v);
1335 _dbus_assert (v == SAMPLE_INT32);
1337 NEXT_EXPECTING_TRUE (&sub);
1338 check_expected_type (&sub, DBUS_TYPE_INT32);
1340 _dbus_type_reader_read_basic (&sub,
1341 (dbus_int32_t*) &v);
1343 _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1345 NEXT_EXPECTING_FALSE (&sub);
1351 write_struct_of_structs (DataBlock *block,
1352 DBusTypeWriter *writer)
1354 DataBlockState saved;
1357 data_block_save (block, &saved);
1359 if (!_dbus_type_writer_recurse_struct (writer,
1363 if (!write_struct_of_int32 (block, &sub))
1365 data_block_restore (block, &saved);
1368 if (!write_struct_of_int32 (block, &sub))
1370 data_block_restore (block, &saved);
1373 if (!write_struct_of_int32 (block, &sub))
1375 data_block_restore (block, &saved);
1379 if (!_dbus_type_writer_unrecurse (writer, &sub))
1381 data_block_restore (block, &saved);
1389 read_struct_of_structs (DataBlock *block,
1390 DBusTypeReader *reader)
1394 check_expected_type (reader, DBUS_TYPE_STRUCT);
1396 _dbus_type_reader_recurse (reader, &sub);
1398 if (!read_struct_of_int32 (block, &sub))
1401 NEXT_EXPECTING_TRUE (&sub);
1402 if (!read_struct_of_int32 (block, &sub))
1405 NEXT_EXPECTING_TRUE (&sub);
1406 if (!read_struct_of_int32 (block, &sub))
1409 NEXT_EXPECTING_FALSE (&sub);
1415 write_struct_of_structs_of_structs (DataBlock *block,
1416 DBusTypeWriter *writer)
1418 DataBlockState saved;
1421 data_block_save (block, &saved);
1423 if (!_dbus_type_writer_recurse_struct (writer,
1427 if (!write_struct_of_structs (block, &sub))
1429 data_block_restore (block, &saved);
1432 if (!write_struct_of_structs (block, &sub))
1434 data_block_restore (block, &saved);
1438 if (!_dbus_type_writer_unrecurse (writer, &sub))
1440 data_block_restore (block, &saved);
1448 read_struct_of_structs_of_structs (DataBlock *block,
1449 DBusTypeReader *reader)
1453 check_expected_type (reader, DBUS_TYPE_STRUCT);
1455 _dbus_type_reader_recurse (reader, &sub);
1457 if (!read_struct_of_structs (block, &sub))
1460 NEXT_EXPECTING_TRUE (&sub);
1461 if (!read_struct_of_structs (block, &sub))
1464 NEXT_EXPECTING_FALSE (&sub);
1470 write_array_of_int32 (DataBlock *block,
1471 DBusTypeWriter *writer)
1474 DataBlockState saved;
1477 data_block_save (block, &saved);
1479 if (!_dbus_type_writer_recurse_array (writer,
1480 DBUS_TYPE_INT32_AS_STRING,
1484 v = SAMPLE_INT32_ALTERNATE;
1485 if (!_dbus_type_writer_write_basic (&sub,
1489 data_block_restore (block, &saved);
1494 if (!_dbus_type_writer_write_basic (&sub,
1498 data_block_restore (block, &saved);
1503 if (!_dbus_type_writer_write_basic (&sub,
1507 data_block_restore (block, &saved);
1511 if (!_dbus_type_writer_unrecurse (writer, &sub))
1513 data_block_restore (block, &saved);
1521 read_array_of_int32 (DataBlock *block,
1522 DBusTypeReader *reader)
1527 check_expected_type (reader, DBUS_TYPE_ARRAY);
1529 _dbus_type_reader_recurse (reader, &sub);
1531 check_expected_type (&sub, DBUS_TYPE_INT32);
1533 _dbus_type_reader_read_basic (&sub,
1534 (dbus_int32_t*) &v);
1536 _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1538 NEXT_EXPECTING_TRUE (&sub);
1539 check_expected_type (&sub, DBUS_TYPE_INT32);
1541 _dbus_type_reader_read_basic (&sub,
1542 (dbus_int32_t*) &v);
1544 _dbus_assert (v == SAMPLE_INT32);
1546 NEXT_EXPECTING_TRUE (&sub);
1547 check_expected_type (&sub, DBUS_TYPE_INT32);
1549 _dbus_type_reader_read_basic (&sub,
1550 (dbus_int32_t*) &v);
1552 _dbus_assert (v == SAMPLE_INT32);
1554 NEXT_EXPECTING_FALSE (&sub);
1561 write_array_of_int32_empty (DataBlock *block,
1562 DBusTypeWriter *writer)
1564 DataBlockState saved;
1567 data_block_save (block, &saved);
1569 if (!_dbus_type_writer_recurse_array (writer,
1570 DBUS_TYPE_INT32_AS_STRING,
1574 if (!_dbus_type_writer_unrecurse (writer, &sub))
1576 data_block_restore (block, &saved);
1584 read_array_of_int32_empty (DataBlock *block,
1585 DBusTypeReader *reader)
1587 check_expected_type (reader, DBUS_TYPE_ARRAY);
1589 /* We are iterating over values not types. Thus we can't recurse
1592 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1598 write_array_of_array_of_int32 (DataBlock *block,
1599 DBusTypeWriter *writer)
1601 DataBlockState saved;
1604 data_block_save (block, &saved);
1606 if (!_dbus_type_writer_recurse_array (writer,
1607 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1611 if (!write_array_of_int32 (block, &sub))
1613 data_block_restore (block, &saved);
1617 if (!write_array_of_int32 (block, &sub))
1619 data_block_restore (block, &saved);
1623 if (!write_array_of_int32_empty (block, &sub))
1625 data_block_restore (block, &saved);
1629 if (!write_array_of_int32 (block, &sub))
1631 data_block_restore (block, &saved);
1635 if (!_dbus_type_writer_unrecurse (writer, &sub))
1637 data_block_restore (block, &saved);
1645 read_array_of_array_of_int32 (DataBlock *block,
1646 DBusTypeReader *reader)
1650 check_expected_type (reader, DBUS_TYPE_ARRAY);
1652 _dbus_type_reader_recurse (reader, &sub);
1654 if (!read_array_of_int32 (block, &sub))
1657 NEXT_EXPECTING_TRUE (&sub);
1658 if (!read_array_of_int32 (block, &sub))
1661 NEXT_EXPECTING_TRUE (&sub);
1662 if (!read_array_of_int32_empty (block, &sub))
1665 NEXT_EXPECTING_TRUE (&sub);
1666 if (!read_array_of_int32 (block, &sub))
1669 NEXT_EXPECTING_FALSE (&sub);
1676 write_array_of_array_of_int32_empty (DataBlock *block,
1677 DBusTypeWriter *writer)
1679 DataBlockState saved;
1682 data_block_save (block, &saved);
1684 if (!_dbus_type_writer_recurse_array (writer,
1685 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1689 if (!_dbus_type_writer_unrecurse (writer, &sub))
1691 data_block_restore (block, &saved);
1699 read_array_of_array_of_int32_empty (DataBlock *block,
1700 DBusTypeReader *reader)
1702 check_expected_type (reader, DBUS_TYPE_ARRAY);
1704 /* We are iterating over values, not types. Thus
1705 * we can't recurse in here.
1708 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1714 write_array_of_array_of_array_of_int32 (DataBlock *block,
1715 DBusTypeWriter *writer)
1717 DataBlockState saved;
1720 data_block_save (block, &saved);
1722 if (!_dbus_type_writer_recurse_array (writer,
1723 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1727 if (!write_array_of_array_of_int32 (block, &sub))
1729 data_block_restore (block, &saved);
1733 if (!write_array_of_array_of_int32 (block, &sub))
1735 data_block_restore (block, &saved);
1739 if (!write_array_of_array_of_int32_empty (block, &sub))
1741 data_block_restore (block, &saved);
1745 if (!_dbus_type_writer_unrecurse (writer, &sub))
1747 data_block_restore (block, &saved);
1755 read_array_of_array_of_array_of_int32 (DataBlock *block,
1756 DBusTypeReader *reader)
1760 check_expected_type (reader, DBUS_TYPE_ARRAY);
1762 _dbus_type_reader_recurse (reader, &sub);
1764 if (!read_array_of_array_of_int32 (block, &sub))
1767 NEXT_EXPECTING_TRUE (&sub);
1768 if (!read_array_of_array_of_int32 (block, &sub))
1771 NEXT_EXPECTING_TRUE (&sub);
1772 if (!read_array_of_array_of_int32_empty (block, &sub))
1775 NEXT_EXPECTING_FALSE (&sub);
1781 write_struct_of_array_of_int32 (DataBlock *block,
1782 DBusTypeWriter *writer)
1784 DataBlockState saved;
1787 data_block_save (block, &saved);
1789 if (!_dbus_type_writer_recurse_struct (writer,
1793 if (!write_array_of_int32 (block, &sub))
1795 data_block_restore (block, &saved);
1799 if (!write_array_of_int32_empty (block, &sub))
1801 data_block_restore (block, &saved);
1805 if (!_dbus_type_writer_unrecurse (writer, &sub))
1807 data_block_restore (block, &saved);
1815 read_struct_of_array_of_int32 (DataBlock *block,
1816 DBusTypeReader *reader)
1820 check_expected_type (reader, DBUS_TYPE_STRUCT);
1822 _dbus_type_reader_recurse (reader, &sub);
1824 check_expected_type (&sub, DBUS_TYPE_ARRAY);
1826 if (!read_array_of_int32 (block, &sub))
1829 NEXT_EXPECTING_TRUE (&sub);
1830 if (!read_array_of_int32_empty (block, &sub))
1833 NEXT_EXPECTING_FALSE (&sub);
1839 write_struct_of_struct_of_array_of_int32 (DataBlock *block,
1840 DBusTypeWriter *writer)
1842 DataBlockState saved;
1845 data_block_save (block, &saved);
1847 if (!_dbus_type_writer_recurse_struct (writer,
1851 if (!write_struct_of_array_of_int32 (block, &sub))
1853 data_block_restore (block, &saved);
1856 if (!write_struct_of_array_of_int32 (block, &sub))
1858 data_block_restore (block, &saved);
1861 if (!write_struct_of_array_of_int32 (block, &sub))
1863 data_block_restore (block, &saved);
1867 if (!_dbus_type_writer_unrecurse (writer, &sub))
1869 data_block_restore (block, &saved);
1877 read_struct_of_struct_of_array_of_int32 (DataBlock *block,
1878 DBusTypeReader *reader)
1882 check_expected_type (reader, DBUS_TYPE_STRUCT);
1884 _dbus_type_reader_recurse (reader, &sub);
1886 if (!read_struct_of_array_of_int32 (block, &sub))
1889 NEXT_EXPECTING_TRUE (&sub);
1890 if (!read_struct_of_array_of_int32 (block, &sub))
1893 NEXT_EXPECTING_TRUE (&sub);
1894 if (!read_struct_of_array_of_int32 (block, &sub))
1897 NEXT_EXPECTING_FALSE (&sub);
1903 write_array_of_struct_of_int32 (DataBlock *block,
1904 DBusTypeWriter *writer)
1906 DataBlockState saved;
1909 data_block_save (block, &saved);
1911 if (!_dbus_type_writer_recurse_array (writer,
1912 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
1913 DBUS_TYPE_INT32_AS_STRING
1914 DBUS_TYPE_INT32_AS_STRING
1915 DBUS_STRUCT_END_CHAR_AS_STRING,
1919 if (!write_struct_of_int32 (block, &sub))
1921 data_block_restore (block, &saved);
1925 if (!write_struct_of_int32 (block, &sub))
1927 data_block_restore (block, &saved);
1931 if (!write_struct_of_int32 (block, &sub))
1933 data_block_restore (block, &saved);
1937 if (!_dbus_type_writer_unrecurse (writer, &sub))
1939 data_block_restore (block, &saved);
1947 read_array_of_struct_of_int32 (DataBlock *block,
1948 DBusTypeReader *reader)
1952 check_expected_type (reader, DBUS_TYPE_ARRAY);
1954 _dbus_type_reader_recurse (reader, &sub);
1956 check_expected_type (&sub, DBUS_TYPE_STRUCT);
1958 if (!read_struct_of_int32 (block, &sub))
1961 NEXT_EXPECTING_TRUE (&sub);
1963 if (!read_struct_of_int32 (block, &sub))
1966 NEXT_EXPECTING_TRUE (&sub);
1968 if (!read_struct_of_int32 (block, &sub))
1971 NEXT_EXPECTING_FALSE (&sub);
1978 write_array_of_array_of_struct_of_int32 (DataBlock *block,
1979 DBusTypeWriter *writer)
1981 DataBlockState saved;
1984 data_block_save (block, &saved);
1986 if (!_dbus_type_writer_recurse_array (writer,
1987 DBUS_TYPE_ARRAY_AS_STRING
1988 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
1989 DBUS_TYPE_INT32_AS_STRING
1990 DBUS_TYPE_INT32_AS_STRING
1991 DBUS_STRUCT_END_CHAR_AS_STRING,
1995 if (!write_array_of_struct_of_int32 (block, &sub))
1997 data_block_restore (block, &saved);
2001 if (!write_array_of_struct_of_int32 (block, &sub))
2003 data_block_restore (block, &saved);
2007 if (!write_array_of_struct_of_int32 (block, &sub))
2009 data_block_restore (block, &saved);
2013 if (!_dbus_type_writer_unrecurse (writer, &sub))
2015 data_block_restore (block, &saved);
2023 read_array_of_array_of_struct_of_int32 (DataBlock *block,
2024 DBusTypeReader *reader)
2028 check_expected_type (reader, DBUS_TYPE_ARRAY);
2030 _dbus_type_reader_recurse (reader, &sub);
2032 check_expected_type (&sub, DBUS_TYPE_ARRAY);
2034 if (!read_array_of_struct_of_int32 (block, &sub))
2037 NEXT_EXPECTING_TRUE (&sub);
2039 if (!read_array_of_struct_of_int32 (block, &sub))
2042 NEXT_EXPECTING_TRUE (&sub);
2044 if (!read_array_of_struct_of_int32 (block, &sub))
2047 NEXT_EXPECTING_FALSE (&sub);
2053 write_struct_of_array_of_struct_of_int32 (DataBlock *block,
2054 DBusTypeWriter *writer)
2056 DataBlockState saved;
2059 data_block_save (block, &saved);
2061 if (!_dbus_type_writer_recurse_struct (writer,
2065 if (!write_array_of_struct_of_int32 (block, &sub))
2067 data_block_restore (block, &saved);
2070 if (!write_array_of_struct_of_int32 (block, &sub))
2072 data_block_restore (block, &saved);
2075 if (!write_array_of_struct_of_int32 (block, &sub))
2077 data_block_restore (block, &saved);
2081 if (!_dbus_type_writer_unrecurse (writer, &sub))
2083 data_block_restore (block, &saved);
2091 read_struct_of_array_of_struct_of_int32 (DataBlock *block,
2092 DBusTypeReader *reader)
2096 check_expected_type (reader, DBUS_TYPE_STRUCT);
2098 _dbus_type_reader_recurse (reader, &sub);
2100 if (!read_array_of_struct_of_int32 (block, &sub))
2103 NEXT_EXPECTING_TRUE (&sub);
2104 if (!read_array_of_struct_of_int32 (block, &sub))
2107 NEXT_EXPECTING_TRUE (&sub);
2108 if (!read_array_of_struct_of_int32 (block, &sub))
2111 NEXT_EXPECTING_FALSE (&sub);
2117 write_array_of_struct_of_array_of_int32 (DataBlock *block,
2118 DBusTypeWriter *writer)
2120 DataBlockState saved;
2123 data_block_save (block, &saved);
2125 if (!_dbus_type_writer_recurse_array (writer,
2126 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2127 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
2128 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
2129 DBUS_STRUCT_END_CHAR_AS_STRING,
2133 if (!write_struct_of_array_of_int32 (block, &sub))
2135 data_block_restore (block, &saved);
2139 if (!write_struct_of_array_of_int32 (block, &sub))
2141 data_block_restore (block, &saved);
2145 if (!write_struct_of_array_of_int32 (block, &sub))
2147 data_block_restore (block, &saved);
2151 if (!_dbus_type_writer_unrecurse (writer, &sub))
2153 data_block_restore (block, &saved);
2161 read_array_of_struct_of_array_of_int32 (DataBlock *block,
2162 DBusTypeReader *reader)
2166 check_expected_type (reader, DBUS_TYPE_ARRAY);
2168 _dbus_type_reader_recurse (reader, &sub);
2170 check_expected_type (&sub, DBUS_TYPE_STRUCT);
2172 if (!read_struct_of_array_of_int32 (block, &sub))
2175 NEXT_EXPECTING_TRUE (&sub);
2177 if (!read_struct_of_array_of_int32 (block, &sub))
2180 NEXT_EXPECTING_TRUE (&sub);
2182 if (!read_struct_of_array_of_int32 (block, &sub))
2185 NEXT_EXPECTING_FALSE (&sub);
2195 ITEM_STRUCT_OF_INT32,
2196 ITEM_STRUCT_OF_STRUCTS,
2197 ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2199 ITEM_ARRAY_OF_INT32,
2200 ITEM_ARRAY_OF_INT32_EMPTY,
2201 ITEM_ARRAY_OF_ARRAY_OF_INT32,
2202 ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2203 ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2205 ITEM_STRUCT_OF_ARRAY_OF_INT32,
2206 ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2208 ITEM_ARRAY_OF_STRUCT_OF_INT32,
2209 ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2211 ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2212 ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2218 typedef dbus_bool_t (* WriteItemFunc) (DataBlock *block,
2219 DBusTypeWriter *writer);
2220 typedef dbus_bool_t (* ReadItemFunc) (DataBlock *block,
2221 DBusTypeReader *reader);
2227 WriteItemFunc write_item_func;
2228 ReadItemFunc read_item_func;
2231 static CheckMarshalItem items[] = {
2233 ITEM_INT32, write_int32, read_int32 },
2234 { "struct with two int32",
2235 ITEM_STRUCT_OF_INT32, write_struct_of_int32, read_struct_of_int32 },
2236 { "struct with three structs of two int32",
2237 ITEM_STRUCT_OF_STRUCTS, write_struct_of_structs, read_struct_of_structs },
2238 { "struct of two structs of three structs of two int32",
2239 ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2240 write_struct_of_structs_of_structs,
2241 read_struct_of_structs_of_structs },
2243 ITEM_ARRAY_OF_INT32, write_array_of_int32, read_array_of_int32 },
2244 { "empty array of int32",
2245 ITEM_ARRAY_OF_INT32_EMPTY, write_array_of_int32_empty, read_array_of_int32_empty },
2246 { "array of array of int32",
2247 ITEM_ARRAY_OF_ARRAY_OF_INT32,
2248 write_array_of_array_of_int32, read_array_of_array_of_int32 },
2249 { "empty array of array of int32",
2250 ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2251 write_array_of_array_of_int32_empty, read_array_of_array_of_int32_empty },
2252 { "array of array of array of int32",
2253 ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2254 write_array_of_array_of_array_of_int32, read_array_of_array_of_array_of_int32 },
2255 { "struct of array of int32",
2256 ITEM_STRUCT_OF_ARRAY_OF_INT32, write_struct_of_array_of_int32, read_struct_of_array_of_int32 },
2257 { "struct of struct of array of int32",
2258 ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2259 write_struct_of_struct_of_array_of_int32, read_struct_of_struct_of_array_of_int32 },
2260 { "array of struct of int32",
2261 ITEM_ARRAY_OF_STRUCT_OF_INT32, write_array_of_struct_of_int32, read_array_of_struct_of_int32 },
2262 { "array of array of struct of int32",
2263 ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2264 write_array_of_array_of_struct_of_int32, read_array_of_array_of_struct_of_int32 },
2266 { "struct of array of struct of int32",
2267 ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2268 write_struct_of_array_of_struct_of_int32, read_struct_of_array_of_struct_of_int32 },
2269 { "array of struct of array of int32",
2270 ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2271 write_array_of_struct_of_array_of_int32, read_array_of_struct_of_array_of_int32 },
2276 /* Array of items from the above items[]; -1 terminated */
2280 static TestRun runs[] = {
2281 { { ITEM_INVALID } },
2284 { { ITEM_INT32, ITEM_INVALID } },
2285 { { ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2286 { { ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2288 /* STRUCT_OF_INT32 */
2289 { { ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2290 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2291 { { ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2292 { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2293 { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2295 /* STRUCT_OF_STRUCTS */
2296 { { ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2297 { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2298 { { ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2299 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2300 { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2301 { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2303 /* STRUCT_OF_STRUCTS_OF_STRUCTS */
2304 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2305 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2306 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2307 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2308 { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2309 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2311 /* ARRAY_OF_INT32 */
2312 { { ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2313 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2314 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2315 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2316 { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2317 { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2318 { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2319 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2320 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2321 { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2323 /* ARRAY_OF_ARRAY_OF_INT32 */
2324 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2325 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2326 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2327 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2328 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2329 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2330 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2331 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2332 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2333 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2335 /* ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32 */
2336 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2337 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2338 { { 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 } },
2339 { { 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 } },
2340 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2341 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2342 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2343 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2344 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2345 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2347 /* STRUCT_OF_ARRAY_OF_INT32 */
2348 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2349 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2350 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2351 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2352 { { ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2353 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2355 /* STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32 */
2356 { { ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2358 /* ARRAY_OF_STRUCT_OF_INT32 */
2359 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2360 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2361 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2362 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2363 { { ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2364 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2366 /* ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32 */
2367 { { ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2369 /* STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32 */
2370 { { ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2372 /* ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32 */
2373 { { ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2378 perform_one_run (DataBlock *block,
2382 DBusTypeReader reader;
2383 DBusTypeWriter writer;
2385 DataBlockState saved;
2391 _dbus_verbose ("run byteorder %s items ",
2392 byte_order == DBUS_LITTLE_ENDIAN ? "little" : "big");
2394 while (run->items[i] != ITEM_INVALID)
2396 CheckMarshalItem *item = &items[run->items[i]];
2398 _dbus_verbose ("%s ", item->desc);
2401 _dbus_verbose (" = %d items\n", i);
2404 data_block_save (block, &saved);
2406 data_block_init_reader_writer (block,
2411 while (run->items[i] != ITEM_INVALID)
2413 CheckMarshalItem *item = &items[run->items[i]];
2415 _dbus_verbose (">>writing %s\n", item->desc);
2417 if (!(* item->write_item_func) (block, &writer))
2423 while (run->items[i] != ITEM_INVALID)
2425 CheckMarshalItem *item = &items[run->items[i]];
2427 _dbus_verbose (">>data for reading %s\n", item->desc);
2429 _dbus_verbose_bytes_of_string (reader.type_str, 0,
2430 _dbus_string_get_length (reader.type_str));
2431 _dbus_verbose_bytes_of_string (reader.value_str, 0,
2432 _dbus_string_get_length (reader.value_str));
2434 _dbus_verbose (">>reading %s\n", item->desc);
2436 if (!(* item->read_item_func) (block, &reader))
2439 _dbus_type_reader_next (&reader);
2447 data_block_restore (block, &saved);
2452 perform_all_runs (int byte_order,
2461 if (!data_block_init (&block))
2464 if (!_dbus_string_lengthen (&block.signature, initial_offset))
2467 if (!_dbus_string_lengthen (&block.body, initial_offset))
2471 while (i < _DBUS_N_ELEMENTS (runs))
2473 if (!perform_one_run (&block, byte_order, &runs[i]))
2482 data_block_free (&block);
2488 perform_all_items (int byte_order,
2498 if (!data_block_init (&block))
2502 if (!_dbus_string_lengthen (&block.signature, initial_offset))
2505 if (!_dbus_string_lengthen (&block.body, initial_offset))
2508 /* Create a run containing all the items */
2510 while (i < _DBUS_N_ELEMENTS (items))
2512 _dbus_assert (i == items[i].which);
2514 run.items[i] = items[i].which;
2519 run.items[i] = ITEM_INVALID;
2521 if (!perform_one_run (&block, byte_order, &run))
2527 data_block_free (&block);
2533 recursive_marshal_test_iteration (void *data)
2540 if (!perform_all_runs (DBUS_LITTLE_ENDIAN, i))
2542 if (!perform_all_runs (DBUS_BIG_ENDIAN, i))
2544 if (!perform_all_items (DBUS_LITTLE_ENDIAN, i))
2546 if (!perform_all_items (DBUS_BIG_ENDIAN, i))
2555 dbus_bool_t _dbus_marshal_recursive_test (void);
2558 _dbus_marshal_recursive_test (void)
2560 _dbus_test_oom_handling ("recursive marshaling",
2561 recursive_marshal_test_iteration,
2569 main (int argc, char **argv)
2571 _dbus_marshal_recursive_test ();
2577 #endif /* DBUS_BUILD_TESTS */