1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-marshal-recursive.c Marshalling routines for recursive types
4 * Copyright (C) 2004 Red Hat, Inc.
6 * Licensed under the Academic Free License version 2.1
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "dbus-marshal-recursive.h"
25 #include "dbus-internals.h"
28 * @addtogroup DBusMarshal
32 struct DBusTypeReaderClass
35 void (* recurse) (DBusTypeReader *sub,
36 DBusTypeReader *parent);
37 int (* get_current_type) (DBusTypeReader *reader);
38 void (* next) (DBusTypeReader *reader,
43 first_type_in_signature (const DBusString *str,
48 t = _dbus_string_get_byte (str, pos);
50 if (t == DBUS_STRUCT_BEGIN_CHAR)
51 return DBUS_TYPE_STRUCT;
57 element_type_get_alignment (const DBusString *str,
60 return _dbus_type_get_alignment (first_type_in_signature (str, pos));
64 reader_init (DBusTypeReader *reader,
66 const DBusString *type_str,
68 const DBusString *value_str,
71 reader->byte_order = byte_order;
72 reader->type_str = type_str;
73 reader->type_pos = type_pos;
74 reader->value_str = value_str;
75 reader->value_pos = value_pos;
79 base_reader_recurse (DBusTypeReader *sub,
80 DBusTypeReader *parent)
82 /* point subreader at the same place as parent */
92 struct_reader_recurse (DBusTypeReader *sub,
93 DBusTypeReader *parent)
95 base_reader_recurse (sub, parent);
97 _dbus_assert (_dbus_string_get_byte (sub->type_str,
98 sub->type_pos) == DBUS_STRUCT_BEGIN_CHAR);
102 /* struct has 8 byte alignment */
103 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
105 sub->u.strct.finished = FALSE;
109 array_reader_recurse (DBusTypeReader *sub,
110 DBusTypeReader *parent)
112 dbus_uint32_t array_len;
115 _dbus_assert (!_dbus_type_reader_array_is_empty (parent));
117 base_reader_recurse (sub, parent);
119 /* point type_pos at the array element type */
122 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
124 _dbus_demarshal_basic_type (sub->value_str,
130 sub->u.array.len = array_len;
132 alignment = element_type_get_alignment (sub->type_str,
135 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
137 sub->u.array.element_type = first_type_in_signature (sub->type_str,
139 sub->u.array.start_pos = sub->value_pos;
141 _dbus_verbose (" type reader %p array start = %d array len = %d array element type = %s\n",
143 sub->u.array.start_pos,
145 _dbus_type_to_string (sub->u.array.element_type));
149 body_reader_get_current_type (DBusTypeReader *reader)
153 t = first_type_in_signature (reader->type_str,
160 struct_reader_get_current_type (DBusTypeReader *reader)
164 if (reader->u.strct.finished)
165 t = DBUS_TYPE_INVALID;
167 t = first_type_in_signature (reader->type_str,
174 array_reader_get_current_type (DBusTypeReader *reader)
179 /* return the array element type if elements remain, and
180 * TYPE_INVALID otherwise
183 end_pos = reader->u.array.start_pos + reader->u.array.len;
185 _dbus_assert (reader->value_pos <= end_pos);
186 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
188 if (reader->value_pos < end_pos)
189 t = reader->u.array.element_type;
191 t = DBUS_TYPE_INVALID;
197 skip_one_complete_type (const DBusString *type_str,
200 while (_dbus_string_get_byte (type_str, *type_pos) == DBUS_TYPE_ARRAY)
203 if (_dbus_string_get_byte (type_str, *type_pos) == DBUS_STRUCT_BEGIN_CHAR)
210 switch (_dbus_string_get_byte (type_str, *type_pos))
212 case DBUS_STRUCT_BEGIN_CHAR:
215 case DBUS_STRUCT_END_CHAR:
218 case DBUS_TYPE_INVALID:
219 _dbus_assert_not_reached ("unbalanced parens in signature");
230 skip_array_values (int element_type,
231 const DBusString *value_str,
235 dbus_uint32_t array_len;
239 pos = _DBUS_ALIGN_VALUE (*value_pos, 4);
241 _dbus_demarshal_basic_type (value_str,
247 alignment = _dbus_type_get_alignment (element_type);
249 pos = _DBUS_ALIGN_VALUE (pos, alignment);
251 *value_pos = pos + array_len;
255 base_reader_next (DBusTypeReader *reader,
258 switch (current_type)
260 case DBUS_TYPE_STRUCT:
261 /* Scan forward over the entire container contents */
265 /* Recurse into the struct */
266 _dbus_type_reader_recurse (reader, &sub);
268 /* Skip everything in this subreader */
269 while (_dbus_type_reader_next (&sub))
274 /* Now we are at the end of this container */
275 reader->type_pos = sub.type_pos;
276 reader->value_pos = sub.value_pos;
280 case DBUS_TYPE_ARRAY:
282 skip_array_values (first_type_in_signature (reader->type_str,
283 reader->type_pos + 1),
284 reader->value_str, &reader->value_pos, reader->byte_order);
285 skip_one_complete_type (reader->type_str, &reader->type_pos);
290 _dbus_marshal_skip_basic_type (reader->value_str,
291 current_type, reader->byte_order,
293 reader->type_pos += 1;
299 struct_reader_next (DBusTypeReader *reader,
304 base_reader_next (reader, current_type);
306 /* for STRUCT containers we return FALSE at the end of the struct,
307 * for INVALID we return FALSE at the end of the signature.
308 * In both cases we arrange for get_current_type() to return INVALID
309 * which is defined to happen iff we're at the end (no more next())
311 t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
312 if (t == DBUS_STRUCT_END_CHAR)
314 reader->type_pos += 1;
315 reader->u.strct.finished = TRUE;
320 array_reader_next (DBusTypeReader *reader,
323 /* Skip one array element */
326 end_pos = reader->u.array.start_pos + reader->u.array.len;
328 _dbus_assert (reader->value_pos < end_pos);
329 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
331 if (reader->u.array.element_type == DBUS_TYPE_STRUCT)
335 /* Recurse into the struct */
336 _dbus_type_reader_recurse (reader, &sub);
338 /* Skip everything in this element */
339 while (_dbus_type_reader_next (&sub))
344 /* Now we are at the end of this element */
345 reader->value_pos = sub.value_pos;
347 else if (reader->u.array.element_type == DBUS_TYPE_ARRAY)
349 skip_array_values (first_type_in_signature (reader->type_str,
350 reader->type_pos + 1),
351 reader->value_str, &reader->value_pos, reader->byte_order);
355 _dbus_marshal_skip_basic_type (reader->value_str,
356 current_type, reader->byte_order,
360 _dbus_assert (reader->value_pos <= end_pos);
362 if (reader->value_pos == end_pos)
364 skip_one_complete_type (reader->type_str,
369 static const DBusTypeReaderClass body_reader_class = {
371 NULL, /* body is always toplevel, so doesn't get recursed into */
372 body_reader_get_current_type,
376 static const DBusTypeReaderClass struct_reader_class = {
378 struct_reader_recurse,
379 struct_reader_get_current_type,
383 static const DBusTypeReaderClass array_reader_class = {
385 array_reader_recurse,
386 array_reader_get_current_type,
391 _dbus_type_reader_init (DBusTypeReader *reader,
393 const DBusString *type_str,
395 const DBusString *value_str,
398 reader->klass = &body_reader_class;
400 reader_init (reader, byte_order, type_str, type_pos,
401 value_str, value_pos);
403 _dbus_verbose (" type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
404 reader, reader->type_pos, reader->value_pos,
405 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
409 _dbus_type_reader_get_current_type (DBusTypeReader *reader)
413 t = (* reader->klass->get_current_type) (reader);
415 _dbus_assert (t != DBUS_STRUCT_END_CHAR);
416 _dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR);
419 _dbus_verbose (" type reader %p current type_pos = %d type = %s\n",
420 reader, reader->type_pos,
421 _dbus_type_to_string (t));
428 _dbus_type_reader_array_is_empty (DBusTypeReader *reader)
430 dbus_uint32_t array_len;
433 _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY,
436 len_pos = _DBUS_ALIGN_VALUE (reader->value_pos, 4);
438 _dbus_demarshal_basic_type (reader->value_str,
444 return array_len == 0;
448 _dbus_type_reader_read_basic (DBusTypeReader *reader,
454 t = _dbus_type_reader_get_current_type (reader);
456 next = reader->value_pos;
457 _dbus_demarshal_basic_type (reader->value_str,
463 _dbus_verbose (" type reader %p read basic type_pos = %d value_pos = %d next = %d remaining sig '%s'\n",
464 reader, reader->type_pos, reader->value_pos, next,
465 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
469 _dbus_type_reader_read_array_of_basic (DBusTypeReader *reader,
479 * Initialize a new reader pointing to the first type and
480 * corresponding value that's a child of the current container. It's
481 * an error to call this if the current type is a non-container.
483 * Note that DBusTypeReader traverses values, not types. So if you
484 * have an empty array of array of int, you can't recurse into it. You
485 * can only recurse into each element.
487 * @param reader the reader
488 * @param sub a reader to init pointing to the first child
491 _dbus_type_reader_recurse (DBusTypeReader *reader,
496 t = first_type_in_signature (reader->type_str, reader->type_pos);
500 case DBUS_TYPE_STRUCT:
501 sub->klass = &struct_reader_class;
503 case DBUS_TYPE_ARRAY:
504 sub->klass = &array_reader_class;
507 _dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t));
508 #ifndef DBUS_DISABLE_CHECKS
509 if (t == DBUS_TYPE_INVALID)
510 _dbus_warn ("You can't recurse into an empty array or off the end of a message body\n");
511 #endif /* DBUS_DISABLE_CHECKS */
513 _dbus_assert_not_reached ("don't yet handle recursing into this type");
516 (* sub->klass->recurse) (sub, reader);
518 _dbus_verbose (" type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
519 sub, sub->type_pos, sub->value_pos,
520 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
524 * Skip to the next value on this "level". e.g. the next field in a
525 * struct, the next value in an array, the next key or value in a
526 * dict. Returns FALSE at the end of the current container.
528 * @param reader the reader
529 * @returns FALSE if nothing more to read at or below this level
532 _dbus_type_reader_next (DBusTypeReader *reader)
536 t = _dbus_type_reader_get_current_type (reader);
538 _dbus_verbose (" type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
539 reader, reader->type_pos, reader->value_pos,
540 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
541 _dbus_type_to_string (t));
543 if (t == DBUS_TYPE_INVALID)
546 (* reader->klass->next) (reader, t);
548 _dbus_verbose (" type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
549 reader, reader->type_pos, reader->value_pos,
550 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
551 _dbus_type_to_string (_dbus_type_reader_get_current_type (reader)));
553 return _dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID;
567 _dbus_type_writer_init (DBusTypeWriter *writer,
569 DBusString *type_str,
571 DBusString *value_str,
574 writer->byte_order = byte_order;
575 writer->type_str = type_str;
576 writer->type_pos = type_pos;
577 writer->value_str = value_str;
578 writer->value_pos = value_pos;
579 writer->container_type = DBUS_TYPE_INVALID;
580 writer->type_pos_is_expectation = FALSE;
582 _dbus_verbose ("writer %p init remaining sig '%s'\n", writer,
583 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
587 _dbus_type_writer_write_basic_no_typecode (DBusTypeWriter *writer,
594 old_value_len = _dbus_string_get_length (writer->value_str);
596 if (!_dbus_marshal_basic_type (writer->value_str,
603 bytes_written = _dbus_string_get_length (writer->value_str) - old_value_len;
605 writer->value_pos += bytes_written;
610 /* If our parent is an array, things are a little bit complicated.
612 * The parent must have a complete element type, such as
613 * "i" or "aai" or "(ii)" or "a(ii)". There can't be
614 * unclosed parens, or an "a" with no following type.
616 * To recurse, the only allowed operation is to recurse into the
617 * first type in the element type. So for "i" you can't recurse, for
618 * "ai" you can recurse into the array, for "(ii)" you can recurse
621 * If you recurse into the array for "ai", then you must specify
622 * "i" for the element type of the array you recurse into.
624 * While inside an array at any level, we need to avoid writing to
625 * type_str, since the type only appears once for the whole array,
626 * it does not appear for each array element.
628 * While inside an array type_pos points to the expected next
629 * typecode, rather than the next place we could write a typecode.
632 writer_recurse_init_and_check (DBusTypeWriter *writer,
636 _dbus_type_writer_init (sub,
643 sub->container_type = container_type;
645 if (writer->type_pos_is_expectation ||
646 (sub->container_type == DBUS_TYPE_ARRAY || sub->container_type == DBUS_TYPE_VARIANT))
647 sub->type_pos_is_expectation = TRUE;
649 sub->type_pos_is_expectation = FALSE;
651 #ifndef DBUS_DISABLE_CHECKS
652 if (writer->type_pos_is_expectation)
656 expected = first_type_in_signature (writer->type_str, writer->type_pos);
658 if (expected != sub->container_type)
660 _dbus_warn ("Writing an element of type %s, but the expected type here is %s\n",
661 _dbus_type_to_string (sub->container_type),
662 _dbus_type_to_string (expected));
663 _dbus_assert_not_reached ("bad array element or variant content written");
666 #endif /* DBUS_DISABLE_CHECKS */
668 _dbus_verbose (" type writer %p recurse parent type_pos = %d value_pos = %d is_expectation = %d container_type = %s remaining sig '%s'\n",
669 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
670 _dbus_type_to_string (writer->container_type),
671 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
672 _dbus_verbose (" type writer %p recurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
673 sub, sub->type_pos, sub->value_pos,
674 sub->type_pos_is_expectation,
675 _dbus_type_to_string (sub->container_type));
679 write_or_verify_typecode (DBusTypeWriter *writer,
682 /* A subwriter inside an array or variant will have type_pos
683 * pointing to the expected typecode; a writer not inside an array
684 * or variant has type_pos pointing to the next place to insert a
687 _dbus_verbose (" type writer %p write_or_verify start type_pos = %d remaining sig '%s'\n",
688 writer, writer->type_pos,
689 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
691 if (writer->type_pos_is_expectation)
693 #ifndef DBUS_DISABLE_CHECKS
697 expected = _dbus_string_get_byte (writer->type_str, writer->type_pos);
699 if (expected != typecode)
701 _dbus_warn ("Array or Variant type requires that type %s be written, but %s was written\n",
702 _dbus_type_to_string (expected), _dbus_type_to_string (typecode));
703 _dbus_assert_not_reached ("bad type inserted somewhere inside an array or variant");
706 #endif /* DBUS_DISABLE_CHECKS */
708 /* if immediately inside an array we'd always be appending an element,
709 * so the expected type doesn't change; if inside a struct or something
710 * below an array, we need to move through said struct or something.
712 if (writer->container_type != DBUS_TYPE_ARRAY)
713 writer->type_pos += 1;
717 if (!_dbus_string_insert_byte (writer->type_str,
722 writer->type_pos += 1;
725 _dbus_verbose (" type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
726 writer, writer->type_pos,
727 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
733 _dbus_type_writer_recurse_struct (DBusTypeWriter *writer,
736 writer_recurse_init_and_check (writer, DBUS_TYPE_STRUCT, sub);
738 /* Ensure that we'll be able to add alignment padding and the typecode */
739 if (!_dbus_string_alloc_space (sub->value_str, 8))
742 if (!write_or_verify_typecode (sub, DBUS_STRUCT_BEGIN_CHAR))
743 _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
745 if (!_dbus_string_insert_bytes (sub->value_str,
747 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
749 _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
750 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
756 _dbus_type_writer_recurse_array (DBusTypeWriter *writer,
757 const char *element_type,
760 int element_type_len;
761 DBusString element_type_str;
762 dbus_uint32_t value = 0;
767 writer_recurse_init_and_check (writer, DBUS_TYPE_ARRAY, sub);
769 #ifndef DBUS_DISABLE_CHECKS
770 if (writer->container_type == DBUS_TYPE_ARRAY)
772 DBusString parent_elements;
774 _dbus_assert (element_type != NULL);
776 _dbus_string_init_const (&parent_elements,
777 _dbus_string_get_const_data_len (writer->type_str,
778 writer->u.array.element_type_pos + 1,
781 if (!_dbus_string_starts_with_c_str (&parent_elements, element_type))
783 _dbus_warn ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
785 _dbus_assert_not_reached ("incompatible type for child array");
788 #endif /* DBUS_DISABLE_CHECKS */
790 _dbus_string_init_const (&element_type_str, element_type);
791 element_type_len = _dbus_string_get_length (&element_type_str);
793 /* 4 bytes for the array length and 4 bytes possible padding */
794 if (!_dbus_string_alloc_space (sub->value_str, 8))
797 sub->type_pos += 1; /* move to point to the element type, since type_pos
798 * should be the expected type for further writes
800 sub->u.array.element_type_pos = sub->type_pos;
802 if (!writer->type_pos_is_expectation)
804 /* sub is a toplevel/outermost array so we need to write the type data */
806 /* alloc space for array typecode, element signature, possible 7
809 if (!_dbus_string_alloc_space (writer->type_str, 1 + element_type_len + 7))
812 if (!_dbus_string_insert_byte (writer->type_str,
815 _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
817 if (!_dbus_string_copy (&element_type_str, 0,
818 sub->type_str, sub->u.array.element_type_pos))
819 _dbus_assert_not_reached ("should not have failed to insert array element typecodes");
822 /* If the parent is an array, we hold type_pos pointing at the array element type;
823 * otherwise advance it to reflect the array value we just recursed into
825 if (writer->container_type != DBUS_TYPE_ARRAY)
826 writer->type_pos += 1 + element_type_len;
828 _dbus_assert (writer->type_pos_is_expectation); /* because it's an array */
830 /* Write the length */
831 sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
833 if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
835 _dbus_assert_not_reached ("should not have failed to insert array len");
837 _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
839 /* Write alignment padding for array elements */
840 _dbus_string_init_const (&str, element_type);
841 alignment = element_type_get_alignment (&str, 0);
843 aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
844 if (aligned != sub->value_pos)
846 if (!_dbus_string_insert_bytes (sub->value_str,
848 aligned - sub->value_pos,
850 _dbus_assert_not_reached ("should not have failed to insert alignment padding");
852 sub->value_pos = aligned;
854 sub->u.array.start_pos = sub->value_pos;
856 _dbus_assert (sub->u.array.start_pos == sub->value_pos);
857 _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
859 _dbus_verbose (" type writer %p recurse array done remaining sig '%s'\n", sub,
860 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
865 /* Variant value will normally have:
866 * 1 byte signature length not including nul
867 * signature typecodes (nul terminated)
868 * padding to 8-boundary
869 * body according to signature
871 * The signature string can only have a single type
872 * in it but that type may be complex/recursive.
874 * So a typical variant type with the integer 3 will have these
876 * 0x1 'i' '\0' [padding to 8-boundary] 0x0 0x0 0x0 0x3
878 * For an array of 4-byte types stuffed into variants, the padding to
879 * 8-boundary is only the 1 byte that is required for the 4-boundary
880 * anyhow for all array elements after the first one. And for single
881 * variants in isolation, wasting a few bytes is hardly a big deal.
883 * The main world of hurt for writing out a variant is that the type
884 * string is the same string as the value string. Which means
885 * inserting to the type string will move the value_pos; and it means
886 * that inserting to the type string could break type alignment.
888 * This type alignment issue is why the body of the variant is always
889 * 8-aligned. Then we know that re-8-aligning the start of the body
890 * will always correctly align the full contents of the variant type.
893 _dbus_type_writer_recurse_variant (DBusTypeWriter *writer,
894 const char *contained_type,
897 int contained_type_len;
898 DBusString contained_type_str;
900 writer_recurse_init_and_check (writer, DBUS_TYPE_VARIANT, sub);
902 _dbus_string_init_const (&contained_type_str, contained_type);
904 contained_type_len = _dbus_string_get_length (&contained_type_str);
906 /* Allocate space for the worst case, which is 1 byte sig
907 * length, nul byte at end of sig, and 7 bytes padding to
910 if (!_dbus_string_alloc_space (sub->value_str, contained_type_len + 9))
913 /* write VARIANT typecode to the parent's type string */
914 if (!write_or_verify_typecode (sub, DBUS_TYPE_VARIANT))
917 if (!_dbus_string_insert_byte (sub->value_str,
920 _dbus_assert_not_reached ("should not have failed to insert variant type sig len");
924 /* Here we switch over to the expected type sig we're about to write */
925 sub->type_str = sub->value_str;
926 sub->type_pos = sub->value_pos;
928 if (!_dbus_string_copy (&contained_type_str, 0,
929 sub->value_str, sub->value_pos))
930 _dbus_assert_not_reached ("should not have failed to insert variant type sig");
932 sub->value_pos += contained_type_len;
934 if (!_dbus_string_insert_byte (sub->value_str,
937 _dbus_assert_not_reached ("should not have failed to insert variant type nul termination");
941 if (!_dbus_string_insert_bytes (sub->value_str,
943 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
945 _dbus_assert_not_reached ("should not have failed to insert alignment padding for variant body");
946 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
952 _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
955 _dbus_assert (sub->type_pos > 0); /* can't be recursed if this fails */
957 /* type_pos_is_expectation never gets unset once set, or we'd get all hosed */
958 _dbus_assert (!writer->type_pos_is_expectation ||
959 (writer->type_pos_is_expectation && sub->type_pos_is_expectation));
961 _dbus_verbose (" type writer %p unrecurse type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
962 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
963 _dbus_type_to_string (writer->container_type));
964 _dbus_verbose (" type writer %p unrecurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
965 sub, sub->type_pos, sub->value_pos,
966 sub->type_pos_is_expectation,
967 _dbus_type_to_string (sub->container_type));
969 if (sub->container_type == DBUS_TYPE_STRUCT)
971 if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
974 else if (sub->container_type == DBUS_TYPE_ARRAY)
978 /* Set the array length */
979 len = sub->value_pos - sub->u.array.start_pos;
980 _dbus_marshal_set_uint32 (sub->value_str,
982 sub->u.array.len_pos,
984 _dbus_verbose (" filled in sub array len to %u at len_pos %d\n",
985 len, sub->u.array.len_pos);
988 /* Now get type_pos right for the parent writer. Here are the cases:
990 * Cases !writer->type_pos_is_expectation:
991 * (in these cases we want to update to the new insertion point)
993 * - if we recursed into a STRUCT then we didn't know in advance
994 * what the types in the struct would be; so we have to fill in
995 * that information now.
996 * writer->type_pos = sub->type_pos
998 * - if we recursed into anything else, we knew the full array
999 * type, or knew the single typecode marking VARIANT, so
1000 * writer->type_pos is already correct.
1001 * writer->type_pos should remain as-is
1003 * - note that the parent is never an ARRAY or VARIANT, if it were
1004 * then type_pos_is_expectation would be TRUE. The parent
1005 * is thus known to be a toplevel or STRUCT.
1007 * Cases where writer->type_pos_is_expectation:
1008 * (in these cases we want to update to next expected type to write)
1010 * - we recursed from STRUCT into STRUCT and we didn't increment
1011 * type_pos in the parent just to stay consistent with the
1012 * !writer->type_pos_is_expectation case (though we could
1013 * special-case this in recurse_struct instead if we wanted)
1014 * writer->type_pos = sub->type_pos
1016 * - we recursed from STRUCT into ARRAY or VARIANT and type_pos
1017 * for parent should have been incremented already
1018 * writer->type_pos should remain as-is
1020 * - we recursed from ARRAY into a sub-element, so type_pos in the
1021 * parent is the element type and should remain the element type
1022 * for the benefit of the next child element
1023 * writer->type_pos should remain as-is
1025 * - we recursed from VARIANT into its value, so type_pos in the
1026 * parent makes no difference since there's only one value
1027 * and we just finished writing it and won't use type_pos again
1028 * writer->type_pos should remain as-is
1030 if (sub->container_type == DBUS_TYPE_STRUCT &&
1031 (writer->container_type == DBUS_TYPE_STRUCT ||
1032 writer->container_type == DBUS_TYPE_INVALID))
1034 /* Advance the parent to the next struct field */
1035 writer->type_pos = sub->type_pos;
1038 writer->value_pos = sub->value_pos;
1040 _dbus_verbose (" type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
1041 writer, writer->type_pos, writer->value_pos,
1042 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
1048 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
1054 /* First ensure that our type realloc will succeed */
1055 if (!_dbus_string_alloc_space (writer->type_str, 1))
1060 if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
1063 if (!write_or_verify_typecode (writer, type))
1064 _dbus_assert_not_reached ("failed to write typecode after prealloc");
1069 _dbus_verbose (" type writer %p basic type_pos = %d value_pos = %d is_expectation = %d\n",
1070 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation);
1076 _dbus_type_writer_write_array (DBusTypeWriter *writer,
1085 /** @} */ /* end of DBusMarshal group */
1087 #ifdef DBUS_BUILD_TESTS
1088 #include "dbus-test.h"
1094 DBusString signature;
1105 data_block_init (DataBlock *block)
1107 if (!_dbus_string_init (&block->signature))
1110 if (!_dbus_string_init (&block->body))
1112 _dbus_string_free (&block->signature);
1120 data_block_free (DataBlock *block)
1122 _dbus_string_free (&block->signature);
1123 _dbus_string_free (&block->body);
1127 data_block_save (DataBlock *block,
1128 DataBlockState *state)
1130 state->saved_sig_len = _dbus_string_get_length (&block->signature);
1131 state->saved_body_len = _dbus_string_get_length (&block->body);
1135 data_block_restore (DataBlock *block,
1136 DataBlockState *state)
1138 /* These set_length should be shortening things so should always work */
1140 if (!_dbus_string_set_length (&block->signature,
1141 state->saved_sig_len))
1142 _dbus_assert_not_reached ("could not restore signature length");
1144 if (!_dbus_string_set_length (&block->body,
1145 state->saved_body_len))
1146 _dbus_assert_not_reached ("could not restore body length");
1150 data_block_init_reader_writer (DataBlock *block,
1152 DBusTypeReader *reader,
1153 DBusTypeWriter *writer)
1155 _dbus_type_reader_init (reader,
1158 _dbus_string_get_length (&block->signature),
1160 _dbus_string_get_length (&block->body));
1162 _dbus_type_writer_init (writer,
1165 _dbus_string_get_length (&block->signature),
1167 _dbus_string_get_length (&block->body));
1170 #define NEXT_EXPECTING_TRUE(reader) do { if (!_dbus_type_reader_next (reader)) \
1172 _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d\n", \
1173 _DBUS_FUNCTION_NAME, __LINE__); \
1174 _dbus_assert_not_reached ("test failed"); \
1178 #define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader)) \
1180 _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d\n", \
1181 _DBUS_FUNCTION_NAME, __LINE__); \
1182 _dbus_assert_not_reached ("test failed"); \
1184 check_expected_type (reader, DBUS_TYPE_INVALID); \
1187 #define SAMPLE_INT32 12345678
1188 #define SAMPLE_INT32_ALTERNATE 53781429
1190 write_int32 (DataBlock *block,
1191 DBusTypeWriter *writer)
1193 dbus_int32_t v = SAMPLE_INT32;
1195 return _dbus_type_writer_write_basic (writer,
1201 real_check_expected_type (DBusTypeReader *reader,
1203 const char *funcname,
1208 t = _dbus_type_reader_get_current_type (reader);
1212 _dbus_warn ("Read type %s while expecting %s at %s line %d\n",
1213 _dbus_type_to_string (t),
1214 _dbus_type_to_string (expected),
1221 #define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__)
1224 read_int32 (DataBlock *block,
1225 DBusTypeReader *reader)
1229 check_expected_type (reader, DBUS_TYPE_INT32);
1231 _dbus_type_reader_read_basic (reader,
1232 (dbus_int32_t*) &v);
1234 _dbus_assert (v == SAMPLE_INT32);
1240 write_struct_of_int32 (DataBlock *block,
1241 DBusTypeWriter *writer)
1244 DataBlockState saved;
1247 data_block_save (block, &saved);
1249 if (!_dbus_type_writer_recurse_struct (writer,
1254 if (!_dbus_type_writer_write_basic (&sub,
1258 data_block_restore (block, &saved);
1262 v = SAMPLE_INT32_ALTERNATE;
1263 if (!_dbus_type_writer_write_basic (&sub,
1267 data_block_restore (block, &saved);
1271 if (!_dbus_type_writer_unrecurse (writer, &sub))
1273 data_block_restore (block, &saved);
1281 read_struct_of_int32 (DataBlock *block,
1282 DBusTypeReader *reader)
1287 check_expected_type (reader, DBUS_TYPE_STRUCT);
1289 _dbus_type_reader_recurse (reader, &sub);
1291 check_expected_type (&sub, DBUS_TYPE_INT32);
1293 _dbus_type_reader_read_basic (&sub,
1294 (dbus_int32_t*) &v);
1296 _dbus_assert (v == SAMPLE_INT32);
1298 NEXT_EXPECTING_TRUE (&sub);
1299 check_expected_type (&sub, DBUS_TYPE_INT32);
1301 _dbus_type_reader_read_basic (&sub,
1302 (dbus_int32_t*) &v);
1304 _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1306 NEXT_EXPECTING_FALSE (&sub);
1312 write_struct_of_structs (DataBlock *block,
1313 DBusTypeWriter *writer)
1315 DataBlockState saved;
1318 data_block_save (block, &saved);
1320 if (!_dbus_type_writer_recurse_struct (writer,
1324 if (!write_struct_of_int32 (block, &sub))
1326 data_block_restore (block, &saved);
1329 if (!write_struct_of_int32 (block, &sub))
1331 data_block_restore (block, &saved);
1334 if (!write_struct_of_int32 (block, &sub))
1336 data_block_restore (block, &saved);
1340 if (!_dbus_type_writer_unrecurse (writer, &sub))
1342 data_block_restore (block, &saved);
1350 read_struct_of_structs (DataBlock *block,
1351 DBusTypeReader *reader)
1355 check_expected_type (reader, DBUS_TYPE_STRUCT);
1357 _dbus_type_reader_recurse (reader, &sub);
1359 if (!read_struct_of_int32 (block, &sub))
1362 NEXT_EXPECTING_TRUE (&sub);
1363 if (!read_struct_of_int32 (block, &sub))
1366 NEXT_EXPECTING_TRUE (&sub);
1367 if (!read_struct_of_int32 (block, &sub))
1370 NEXT_EXPECTING_FALSE (&sub);
1376 write_struct_of_structs_of_structs (DataBlock *block,
1377 DBusTypeWriter *writer)
1379 DataBlockState saved;
1382 data_block_save (block, &saved);
1384 if (!_dbus_type_writer_recurse_struct (writer,
1388 if (!write_struct_of_structs (block, &sub))
1390 data_block_restore (block, &saved);
1393 if (!write_struct_of_structs (block, &sub))
1395 data_block_restore (block, &saved);
1399 if (!_dbus_type_writer_unrecurse (writer, &sub))
1401 data_block_restore (block, &saved);
1409 read_struct_of_structs_of_structs (DataBlock *block,
1410 DBusTypeReader *reader)
1414 check_expected_type (reader, DBUS_TYPE_STRUCT);
1416 _dbus_type_reader_recurse (reader, &sub);
1418 if (!read_struct_of_structs (block, &sub))
1421 NEXT_EXPECTING_TRUE (&sub);
1422 if (!read_struct_of_structs (block, &sub))
1425 NEXT_EXPECTING_FALSE (&sub);
1431 write_array_of_int32 (DataBlock *block,
1432 DBusTypeWriter *writer)
1435 DataBlockState saved;
1438 data_block_save (block, &saved);
1440 if (!_dbus_type_writer_recurse_array (writer,
1441 DBUS_TYPE_INT32_AS_STRING,
1445 v = SAMPLE_INT32_ALTERNATE;
1446 if (!_dbus_type_writer_write_basic (&sub,
1450 data_block_restore (block, &saved);
1455 if (!_dbus_type_writer_write_basic (&sub,
1459 data_block_restore (block, &saved);
1464 if (!_dbus_type_writer_write_basic (&sub,
1468 data_block_restore (block, &saved);
1472 if (!_dbus_type_writer_unrecurse (writer, &sub))
1474 data_block_restore (block, &saved);
1482 read_array_of_int32 (DataBlock *block,
1483 DBusTypeReader *reader)
1488 check_expected_type (reader, DBUS_TYPE_ARRAY);
1490 _dbus_type_reader_recurse (reader, &sub);
1492 check_expected_type (&sub, DBUS_TYPE_INT32);
1494 _dbus_type_reader_read_basic (&sub,
1495 (dbus_int32_t*) &v);
1497 _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1499 NEXT_EXPECTING_TRUE (&sub);
1500 check_expected_type (&sub, DBUS_TYPE_INT32);
1502 _dbus_type_reader_read_basic (&sub,
1503 (dbus_int32_t*) &v);
1505 _dbus_assert (v == SAMPLE_INT32);
1507 NEXT_EXPECTING_TRUE (&sub);
1508 check_expected_type (&sub, DBUS_TYPE_INT32);
1510 _dbus_type_reader_read_basic (&sub,
1511 (dbus_int32_t*) &v);
1513 _dbus_assert (v == SAMPLE_INT32);
1515 NEXT_EXPECTING_FALSE (&sub);
1522 write_array_of_int32_empty (DataBlock *block,
1523 DBusTypeWriter *writer)
1525 DataBlockState saved;
1528 data_block_save (block, &saved);
1530 if (!_dbus_type_writer_recurse_array (writer,
1531 DBUS_TYPE_INT32_AS_STRING,
1535 if (!_dbus_type_writer_unrecurse (writer, &sub))
1537 data_block_restore (block, &saved);
1545 read_array_of_int32_empty (DataBlock *block,
1546 DBusTypeReader *reader)
1548 check_expected_type (reader, DBUS_TYPE_ARRAY);
1550 /* We are iterating over values not types. Thus we can't recurse
1553 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1559 write_array_of_array_of_int32 (DataBlock *block,
1560 DBusTypeWriter *writer)
1562 DataBlockState saved;
1565 data_block_save (block, &saved);
1567 if (!_dbus_type_writer_recurse_array (writer,
1568 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1572 if (!write_array_of_int32 (block, &sub))
1574 data_block_restore (block, &saved);
1578 if (!write_array_of_int32 (block, &sub))
1580 data_block_restore (block, &saved);
1584 if (!write_array_of_int32_empty (block, &sub))
1586 data_block_restore (block, &saved);
1590 if (!write_array_of_int32 (block, &sub))
1592 data_block_restore (block, &saved);
1596 if (!_dbus_type_writer_unrecurse (writer, &sub))
1598 data_block_restore (block, &saved);
1606 read_array_of_array_of_int32 (DataBlock *block,
1607 DBusTypeReader *reader)
1611 check_expected_type (reader, DBUS_TYPE_ARRAY);
1613 _dbus_type_reader_recurse (reader, &sub);
1615 if (!read_array_of_int32 (block, &sub))
1618 NEXT_EXPECTING_TRUE (&sub);
1619 if (!read_array_of_int32 (block, &sub))
1622 NEXT_EXPECTING_TRUE (&sub);
1623 if (!read_array_of_int32_empty (block, &sub))
1626 NEXT_EXPECTING_TRUE (&sub);
1627 if (!read_array_of_int32 (block, &sub))
1630 NEXT_EXPECTING_FALSE (&sub);
1637 write_array_of_array_of_int32_empty (DataBlock *block,
1638 DBusTypeWriter *writer)
1640 DataBlockState saved;
1643 data_block_save (block, &saved);
1645 if (!_dbus_type_writer_recurse_array (writer,
1646 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1650 if (!_dbus_type_writer_unrecurse (writer, &sub))
1652 data_block_restore (block, &saved);
1660 read_array_of_array_of_int32_empty (DataBlock *block,
1661 DBusTypeReader *reader)
1663 check_expected_type (reader, DBUS_TYPE_ARRAY);
1665 /* We are iterating over values, not types. Thus
1666 * we can't recurse in here.
1669 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1675 write_array_of_array_of_array_of_int32 (DataBlock *block,
1676 DBusTypeWriter *writer)
1678 DataBlockState saved;
1681 data_block_save (block, &saved);
1683 if (!_dbus_type_writer_recurse_array (writer,
1684 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1688 if (!write_array_of_array_of_int32 (block, &sub))
1690 data_block_restore (block, &saved);
1694 if (!write_array_of_array_of_int32 (block, &sub))
1696 data_block_restore (block, &saved);
1700 if (!write_array_of_array_of_int32_empty (block, &sub))
1702 data_block_restore (block, &saved);
1706 if (!_dbus_type_writer_unrecurse (writer, &sub))
1708 data_block_restore (block, &saved);
1716 read_array_of_array_of_array_of_int32 (DataBlock *block,
1717 DBusTypeReader *reader)
1721 check_expected_type (reader, DBUS_TYPE_ARRAY);
1723 _dbus_type_reader_recurse (reader, &sub);
1725 if (!read_array_of_array_of_int32 (block, &sub))
1728 NEXT_EXPECTING_TRUE (&sub);
1729 if (!read_array_of_array_of_int32 (block, &sub))
1732 NEXT_EXPECTING_TRUE (&sub);
1733 if (!read_array_of_array_of_int32_empty (block, &sub))
1736 NEXT_EXPECTING_FALSE (&sub);
1742 write_struct_of_array_of_int32 (DataBlock *block,
1743 DBusTypeWriter *writer)
1745 DataBlockState saved;
1748 data_block_save (block, &saved);
1750 if (!_dbus_type_writer_recurse_struct (writer,
1754 if (!write_array_of_int32 (block, &sub))
1756 data_block_restore (block, &saved);
1760 if (!write_array_of_int32_empty (block, &sub))
1762 data_block_restore (block, &saved);
1766 if (!_dbus_type_writer_unrecurse (writer, &sub))
1768 data_block_restore (block, &saved);
1776 read_struct_of_array_of_int32 (DataBlock *block,
1777 DBusTypeReader *reader)
1781 check_expected_type (reader, DBUS_TYPE_STRUCT);
1783 _dbus_type_reader_recurse (reader, &sub);
1785 check_expected_type (&sub, DBUS_TYPE_ARRAY);
1787 if (!read_array_of_int32 (block, &sub))
1790 NEXT_EXPECTING_TRUE (&sub);
1791 if (!read_array_of_int32_empty (block, &sub))
1794 NEXT_EXPECTING_FALSE (&sub);
1800 write_struct_of_struct_of_array_of_int32 (DataBlock *block,
1801 DBusTypeWriter *writer)
1803 DataBlockState saved;
1806 data_block_save (block, &saved);
1808 if (!_dbus_type_writer_recurse_struct (writer,
1812 if (!write_struct_of_array_of_int32 (block, &sub))
1814 data_block_restore (block, &saved);
1817 if (!write_struct_of_array_of_int32 (block, &sub))
1819 data_block_restore (block, &saved);
1822 if (!write_struct_of_array_of_int32 (block, &sub))
1824 data_block_restore (block, &saved);
1828 if (!_dbus_type_writer_unrecurse (writer, &sub))
1830 data_block_restore (block, &saved);
1838 read_struct_of_struct_of_array_of_int32 (DataBlock *block,
1839 DBusTypeReader *reader)
1843 check_expected_type (reader, DBUS_TYPE_STRUCT);
1845 _dbus_type_reader_recurse (reader, &sub);
1847 if (!read_struct_of_array_of_int32 (block, &sub))
1850 NEXT_EXPECTING_TRUE (&sub);
1851 if (!read_struct_of_array_of_int32 (block, &sub))
1854 NEXT_EXPECTING_TRUE (&sub);
1855 if (!read_struct_of_array_of_int32 (block, &sub))
1858 NEXT_EXPECTING_FALSE (&sub);
1864 write_array_of_struct_of_int32 (DataBlock *block,
1865 DBusTypeWriter *writer)
1867 DataBlockState saved;
1870 data_block_save (block, &saved);
1872 if (!_dbus_type_writer_recurse_array (writer,
1873 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
1874 DBUS_TYPE_INT32_AS_STRING
1875 DBUS_TYPE_INT32_AS_STRING
1876 DBUS_STRUCT_END_CHAR_AS_STRING,
1880 if (!write_struct_of_int32 (block, &sub))
1882 data_block_restore (block, &saved);
1886 if (!write_struct_of_int32 (block, &sub))
1888 data_block_restore (block, &saved);
1892 if (!write_struct_of_int32 (block, &sub))
1894 data_block_restore (block, &saved);
1898 if (!_dbus_type_writer_unrecurse (writer, &sub))
1900 data_block_restore (block, &saved);
1908 read_array_of_struct_of_int32 (DataBlock *block,
1909 DBusTypeReader *reader)
1913 check_expected_type (reader, DBUS_TYPE_ARRAY);
1915 _dbus_type_reader_recurse (reader, &sub);
1917 check_expected_type (&sub, DBUS_TYPE_STRUCT);
1919 if (!read_struct_of_int32 (block, &sub))
1922 NEXT_EXPECTING_TRUE (&sub);
1924 if (!read_struct_of_int32 (block, &sub))
1927 NEXT_EXPECTING_TRUE (&sub);
1929 if (!read_struct_of_int32 (block, &sub))
1932 NEXT_EXPECTING_FALSE (&sub);
1939 write_array_of_array_of_struct_of_int32 (DataBlock *block,
1940 DBusTypeWriter *writer)
1942 DataBlockState saved;
1945 data_block_save (block, &saved);
1947 if (!_dbus_type_writer_recurse_array (writer,
1948 DBUS_TYPE_ARRAY_AS_STRING
1949 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
1950 DBUS_TYPE_INT32_AS_STRING
1951 DBUS_TYPE_INT32_AS_STRING
1952 DBUS_STRUCT_END_CHAR_AS_STRING,
1956 if (!write_array_of_struct_of_int32 (block, &sub))
1958 data_block_restore (block, &saved);
1962 if (!write_array_of_struct_of_int32 (block, &sub))
1964 data_block_restore (block, &saved);
1968 if (!write_array_of_struct_of_int32 (block, &sub))
1970 data_block_restore (block, &saved);
1974 if (!_dbus_type_writer_unrecurse (writer, &sub))
1976 data_block_restore (block, &saved);
1984 read_array_of_array_of_struct_of_int32 (DataBlock *block,
1985 DBusTypeReader *reader)
1989 check_expected_type (reader, DBUS_TYPE_ARRAY);
1991 _dbus_type_reader_recurse (reader, &sub);
1993 check_expected_type (&sub, DBUS_TYPE_ARRAY);
1995 if (!read_array_of_struct_of_int32 (block, &sub))
1998 NEXT_EXPECTING_TRUE (&sub);
2000 if (!read_array_of_struct_of_int32 (block, &sub))
2003 NEXT_EXPECTING_TRUE (&sub);
2005 if (!read_array_of_struct_of_int32 (block, &sub))
2008 NEXT_EXPECTING_FALSE (&sub);
2014 write_struct_of_array_of_struct_of_int32 (DataBlock *block,
2015 DBusTypeWriter *writer)
2017 DataBlockState saved;
2020 data_block_save (block, &saved);
2022 if (!_dbus_type_writer_recurse_struct (writer,
2026 if (!write_array_of_struct_of_int32 (block, &sub))
2028 data_block_restore (block, &saved);
2031 if (!write_array_of_struct_of_int32 (block, &sub))
2033 data_block_restore (block, &saved);
2036 if (!write_array_of_struct_of_int32 (block, &sub))
2038 data_block_restore (block, &saved);
2042 if (!_dbus_type_writer_unrecurse (writer, &sub))
2044 data_block_restore (block, &saved);
2052 read_struct_of_array_of_struct_of_int32 (DataBlock *block,
2053 DBusTypeReader *reader)
2057 check_expected_type (reader, DBUS_TYPE_STRUCT);
2059 _dbus_type_reader_recurse (reader, &sub);
2061 if (!read_array_of_struct_of_int32 (block, &sub))
2064 NEXT_EXPECTING_TRUE (&sub);
2065 if (!read_array_of_struct_of_int32 (block, &sub))
2068 NEXT_EXPECTING_TRUE (&sub);
2069 if (!read_array_of_struct_of_int32 (block, &sub))
2072 NEXT_EXPECTING_FALSE (&sub);
2078 write_array_of_struct_of_array_of_int32 (DataBlock *block,
2079 DBusTypeWriter *writer)
2081 DataBlockState saved;
2084 data_block_save (block, &saved);
2086 if (!_dbus_type_writer_recurse_array (writer,
2087 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2088 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
2089 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
2090 DBUS_STRUCT_END_CHAR_AS_STRING,
2094 if (!write_struct_of_array_of_int32 (block, &sub))
2096 data_block_restore (block, &saved);
2100 if (!write_struct_of_array_of_int32 (block, &sub))
2102 data_block_restore (block, &saved);
2106 if (!write_struct_of_array_of_int32 (block, &sub))
2108 data_block_restore (block, &saved);
2112 if (!_dbus_type_writer_unrecurse (writer, &sub))
2114 data_block_restore (block, &saved);
2122 read_array_of_struct_of_array_of_int32 (DataBlock *block,
2123 DBusTypeReader *reader)
2127 check_expected_type (reader, DBUS_TYPE_ARRAY);
2129 _dbus_type_reader_recurse (reader, &sub);
2131 check_expected_type (&sub, DBUS_TYPE_STRUCT);
2133 if (!read_struct_of_array_of_int32 (block, &sub))
2136 NEXT_EXPECTING_TRUE (&sub);
2138 if (!read_struct_of_array_of_int32 (block, &sub))
2141 NEXT_EXPECTING_TRUE (&sub);
2143 if (!read_struct_of_array_of_int32 (block, &sub))
2146 NEXT_EXPECTING_FALSE (&sub);
2156 ITEM_STRUCT_OF_INT32,
2157 ITEM_STRUCT_OF_STRUCTS,
2158 ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2160 ITEM_ARRAY_OF_INT32,
2161 ITEM_ARRAY_OF_INT32_EMPTY,
2162 ITEM_ARRAY_OF_ARRAY_OF_INT32,
2163 ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2164 ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2166 ITEM_STRUCT_OF_ARRAY_OF_INT32,
2167 ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2169 ITEM_ARRAY_OF_STRUCT_OF_INT32,
2170 ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2172 ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2173 ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2179 typedef dbus_bool_t (* WriteItemFunc) (DataBlock *block,
2180 DBusTypeWriter *writer);
2181 typedef dbus_bool_t (* ReadItemFunc) (DataBlock *block,
2182 DBusTypeReader *reader);
2188 WriteItemFunc write_item_func;
2189 ReadItemFunc read_item_func;
2192 static CheckMarshalItem items[] = {
2194 ITEM_INT32, write_int32, read_int32 },
2195 { "struct with two int32",
2196 ITEM_STRUCT_OF_INT32, write_struct_of_int32, read_struct_of_int32 },
2197 { "struct with three structs of two int32",
2198 ITEM_STRUCT_OF_STRUCTS, write_struct_of_structs, read_struct_of_structs },
2199 { "struct of two structs of three structs of two int32",
2200 ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2201 write_struct_of_structs_of_structs,
2202 read_struct_of_structs_of_structs },
2204 ITEM_ARRAY_OF_INT32, write_array_of_int32, read_array_of_int32 },
2205 { "empty array of int32",
2206 ITEM_ARRAY_OF_INT32_EMPTY, write_array_of_int32_empty, read_array_of_int32_empty },
2207 { "array of array of int32",
2208 ITEM_ARRAY_OF_ARRAY_OF_INT32,
2209 write_array_of_array_of_int32, read_array_of_array_of_int32 },
2210 { "empty array of array of int32",
2211 ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2212 write_array_of_array_of_int32_empty, read_array_of_array_of_int32_empty },
2213 { "array of array of array of int32",
2214 ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2215 write_array_of_array_of_array_of_int32, read_array_of_array_of_array_of_int32 },
2216 { "struct of array of int32",
2217 ITEM_STRUCT_OF_ARRAY_OF_INT32, write_struct_of_array_of_int32, read_struct_of_array_of_int32 },
2218 { "struct of struct of array of int32",
2219 ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2220 write_struct_of_struct_of_array_of_int32, read_struct_of_struct_of_array_of_int32 },
2221 { "array of struct of int32",
2222 ITEM_ARRAY_OF_STRUCT_OF_INT32, write_array_of_struct_of_int32, read_array_of_struct_of_int32 },
2223 { "array of array of struct of int32",
2224 ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2225 write_array_of_array_of_struct_of_int32, read_array_of_array_of_struct_of_int32 },
2227 { "struct of array of struct of int32",
2228 ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2229 write_struct_of_array_of_struct_of_int32, read_struct_of_array_of_struct_of_int32 },
2230 { "array of struct of array of int32",
2231 ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2232 write_array_of_struct_of_array_of_int32, read_array_of_struct_of_array_of_int32 },
2237 /* Array of items from the above items[]; -1 terminated */
2241 static TestRun runs[] = {
2242 { { ITEM_INVALID } },
2245 { { ITEM_INT32, ITEM_INVALID } },
2246 { { ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2247 { { ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2249 /* STRUCT_OF_INT32 */
2250 { { ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2251 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2252 { { ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2253 { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2254 { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2256 /* STRUCT_OF_STRUCTS */
2257 { { ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2258 { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2259 { { ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2260 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2261 { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2262 { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2264 /* STRUCT_OF_STRUCTS_OF_STRUCTS */
2265 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2266 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2267 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2268 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2269 { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2270 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2272 /* ARRAY_OF_INT32 */
2273 { { ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2274 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2275 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2276 { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2277 { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2278 { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2279 { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2280 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2281 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2282 { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2284 /* ARRAY_OF_ARRAY_OF_INT32 */
2285 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2286 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2287 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2288 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2289 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2290 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2291 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2292 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2293 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2294 { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2296 /* ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32 */
2297 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2298 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2299 { { 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 } },
2300 { { 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 } },
2301 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2302 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2303 { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2304 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2305 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2306 { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2308 /* STRUCT_OF_ARRAY_OF_INT32 */
2309 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2310 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2311 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2312 { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2313 { { ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2314 { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2316 /* STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32 */
2317 { { ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2319 /* ARRAY_OF_STRUCT_OF_INT32 */
2320 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2321 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2322 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2323 { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2324 { { ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2325 { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2327 /* ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32 */
2328 { { ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2330 /* STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32 */
2331 { { ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2333 /* ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32 */
2334 { { ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2339 perform_one_run (DataBlock *block,
2343 DBusTypeReader reader;
2344 DBusTypeWriter writer;
2346 DataBlockState saved;
2352 _dbus_verbose ("run byteorder %s items ",
2353 byte_order == DBUS_LITTLE_ENDIAN ? "little" : "big");
2355 while (run->items[i] != ITEM_INVALID)
2357 CheckMarshalItem *item = &items[run->items[i]];
2359 _dbus_verbose ("%s ", item->desc);
2362 _dbus_verbose (" = %d items\n", i);
2365 data_block_save (block, &saved);
2367 data_block_init_reader_writer (block,
2372 while (run->items[i] != ITEM_INVALID)
2374 CheckMarshalItem *item = &items[run->items[i]];
2376 _dbus_verbose (">>writing %s\n", item->desc);
2378 if (!(* item->write_item_func) (block, &writer))
2384 while (run->items[i] != ITEM_INVALID)
2386 CheckMarshalItem *item = &items[run->items[i]];
2388 _dbus_verbose (">>data for reading %s\n", item->desc);
2390 _dbus_verbose_bytes_of_string (reader.type_str, 0,
2391 _dbus_string_get_length (reader.type_str));
2392 _dbus_verbose_bytes_of_string (reader.value_str, 0,
2393 _dbus_string_get_length (reader.value_str));
2395 _dbus_verbose (">>reading %s\n", item->desc);
2397 if (!(* item->read_item_func) (block, &reader))
2400 _dbus_type_reader_next (&reader);
2408 data_block_restore (block, &saved);
2413 perform_all_runs (int byte_order,
2422 if (!data_block_init (&block))
2425 if (!_dbus_string_lengthen (&block.signature, initial_offset))
2428 if (!_dbus_string_lengthen (&block.body, initial_offset))
2432 while (i < _DBUS_N_ELEMENTS (runs))
2434 if (!perform_one_run (&block, byte_order, &runs[i]))
2443 data_block_free (&block);
2449 perform_all_items (int byte_order,
2459 if (!data_block_init (&block))
2463 if (!_dbus_string_lengthen (&block.signature, initial_offset))
2466 if (!_dbus_string_lengthen (&block.body, initial_offset))
2469 /* Create a run containing all the items */
2471 while (i < _DBUS_N_ELEMENTS (items))
2473 _dbus_assert (i == items[i].which);
2475 run.items[i] = items[i].which;
2480 run.items[i] = ITEM_INVALID;
2482 if (!perform_one_run (&block, byte_order, &run))
2488 data_block_free (&block);
2494 recursive_marshal_test_iteration (void *data)
2501 if (!perform_all_runs (DBUS_LITTLE_ENDIAN, i))
2503 if (!perform_all_runs (DBUS_BIG_ENDIAN, i))
2505 if (!perform_all_items (DBUS_LITTLE_ENDIAN, i))
2507 if (!perform_all_items (DBUS_BIG_ENDIAN, i))
2516 dbus_bool_t _dbus_marshal_recursive_test (void);
2519 _dbus_marshal_recursive_test (void)
2521 _dbus_test_oom_handling ("recursive marshaling",
2522 recursive_marshal_test_iteration,
2530 main (int argc, char **argv)
2532 _dbus_marshal_recursive_test ();
2538 #endif /* DBUS_BUILD_TESTS */