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-marshal-basic.h"
26 #include "dbus-internals.h"
29 * @addtogroup DBusMarshal
32 #define RECURSIVE_MARSHAL_TRACE 0
34 struct DBusTypeReaderClass
37 int id; /* index in all_reader_classes */
38 dbus_bool_t types_only; /* only iterates over types, not values */
39 void (* recurse) (DBusTypeReader *sub,
40 DBusTypeReader *parent);
41 int (* get_current_type) (DBusTypeReader *reader);
42 void (* next) (DBusTypeReader *reader,
44 void (* init_from_mark) (DBusTypeReader *reader,
45 const DBusTypeMark *mark);
49 first_type_in_signature (const DBusString *str,
54 t = _dbus_string_get_byte (str, pos);
56 if (t == DBUS_STRUCT_BEGIN_CHAR)
57 return DBUS_TYPE_STRUCT;
63 element_type_get_alignment (const DBusString *str,
66 return _dbus_type_get_alignment (first_type_in_signature (str, pos));
70 reader_init (DBusTypeReader *reader,
72 const DBusString *type_str,
74 const DBusString *value_str,
77 reader->byte_order = byte_order;
78 reader->finished = FALSE;
79 reader->type_str = type_str;
80 reader->type_pos = type_pos;
81 reader->value_str = value_str;
82 reader->value_pos = value_pos;
86 base_reader_recurse (DBusTypeReader *sub,
87 DBusTypeReader *parent)
89 /* point subreader at the same place as parent */
99 struct_types_only_reader_recurse (DBusTypeReader *sub,
100 DBusTypeReader *parent)
102 base_reader_recurse (sub, parent);
104 _dbus_assert (_dbus_string_get_byte (sub->type_str,
105 sub->type_pos) == DBUS_STRUCT_BEGIN_CHAR);
111 struct_reader_recurse (DBusTypeReader *sub,
112 DBusTypeReader *parent)
114 struct_types_only_reader_recurse (sub, parent);
116 /* struct has 8 byte alignment */
117 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
121 array_types_only_reader_recurse (DBusTypeReader *sub,
122 DBusTypeReader *parent)
124 base_reader_recurse (sub, parent);
126 /* point type_pos at the array element type */
129 /* Init with values likely to crash things if misused */
130 sub->u.array.start_pos = _DBUS_INT_MAX;
131 sub->array_len_offset = 7;
135 array_reader_get_array_len (DBusTypeReader *reader)
137 dbus_uint32_t array_len;
140 /* array_len_offset is the offset back from start_pos to end of the len */
141 len_pos = reader->u.array.start_pos - ((int)reader->array_len_offset) - 4;
143 _dbus_demarshal_basic_type (reader->value_str,
149 _dbus_verbose (" reader %p len_pos %d array len %u len_offset %d\n",
150 reader, len_pos, array_len, reader->array_len_offset);
152 _dbus_assert (reader->u.array.start_pos - len_pos - 4 < 8);
158 array_reader_recurse (DBusTypeReader *sub,
159 DBusTypeReader *parent)
164 _dbus_assert (!_dbus_type_reader_array_is_empty (parent));
166 array_types_only_reader_recurse (sub, parent);
168 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
170 len_pos = sub->value_pos;
172 sub->value_pos += 4; /* for the length */
174 alignment = element_type_get_alignment (sub->type_str,
177 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
179 sub->u.array.start_pos = sub->value_pos;
180 _dbus_assert ((sub->u.array.start_pos - (len_pos + 4)) < 8); /* only 3 bits in array_len_offset */
181 sub->array_len_offset = sub->u.array.start_pos - (len_pos + 4);
183 #if RECURSIVE_MARSHAL_TRACE
184 _dbus_verbose (" type reader %p array start = %d len_offset = %d array len = %d array element type = %s\n",
186 sub->u.array.start_pos,
187 sub->array_len_offset,
188 array_reader_get_array_len (sub),
189 _dbus_type_to_string (first_type_in_signature (sub->type_str,
195 variant_reader_recurse (DBusTypeReader *sub,
196 DBusTypeReader *parent)
200 base_reader_recurse (sub, parent);
202 /* Variant is 1 byte sig length (without nul), signature with nul,
203 * padding to 8-boundary, then values
206 sig_len = _dbus_string_get_byte (sub->value_str, sub->value_pos);
208 sub->type_str = sub->value_str;
209 sub->type_pos = sub->value_pos + 1;
211 sub->value_pos = sub->type_pos + sig_len + 1;
213 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
215 #if RECURSIVE_MARSHAL_TRACE
216 _dbus_verbose (" type reader %p variant containing '%s'\n",
218 _dbus_string_get_const_data_len (sub->type_str,
224 base_reader_get_current_type (DBusTypeReader *reader)
228 t = first_type_in_signature (reader->type_str,
235 struct_reader_get_current_type (DBusTypeReader *reader)
239 if (reader->finished)
240 t = DBUS_TYPE_INVALID;
242 t = first_type_in_signature (reader->type_str,
249 array_types_only_reader_get_current_type (DBusTypeReader *reader)
253 if (reader->finished)
254 t = DBUS_TYPE_INVALID;
256 t = first_type_in_signature (reader->type_str,
263 array_reader_get_current_type (DBusTypeReader *reader)
268 /* return the array element type if elements remain, and
269 * TYPE_INVALID otherwise
272 end_pos = reader->u.array.start_pos + array_reader_get_array_len (reader);
274 _dbus_assert (reader->value_pos <= end_pos);
275 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
277 if (reader->value_pos < end_pos)
278 t = first_type_in_signature (reader->type_str,
281 t = DBUS_TYPE_INVALID;
287 skip_one_complete_type (const DBusString *type_str,
290 while (_dbus_string_get_byte (type_str, *type_pos) == DBUS_TYPE_ARRAY)
293 if (_dbus_string_get_byte (type_str, *type_pos) == DBUS_STRUCT_BEGIN_CHAR)
300 switch (_dbus_string_get_byte (type_str, *type_pos))
302 case DBUS_STRUCT_BEGIN_CHAR:
305 case DBUS_STRUCT_END_CHAR:
308 case DBUS_TYPE_INVALID:
309 _dbus_assert_not_reached ("unbalanced parens in signature");
320 base_reader_next (DBusTypeReader *reader,
323 switch (current_type)
325 case DBUS_TYPE_STRUCT:
326 case DBUS_TYPE_VARIANT:
327 /* Scan forward over the entire container contents */
331 /* Recurse into the struct or variant */
332 _dbus_type_reader_recurse (reader, &sub);
334 /* Skip everything in this subreader */
335 while (_dbus_type_reader_next (&sub))
340 /* Now we are at the end of this container; for variants, the
341 * subreader's type_pos is totally inapplicable (it's in the
342 * value string) but we know that we increment by one past the
345 if (current_type == DBUS_TYPE_VARIANT)
346 reader->type_pos += 1;
348 reader->type_pos = sub.type_pos;
350 if (!reader->klass->types_only)
351 reader->value_pos = sub.value_pos;
355 case DBUS_TYPE_ARRAY:
357 if (!reader->klass->types_only)
358 _dbus_marshal_skip_array (reader->value_str, reader->byte_order,
359 first_type_in_signature (reader->type_str,
360 reader->type_pos + 1),
363 skip_one_complete_type (reader->type_str, &reader->type_pos);
368 if (!reader->klass->types_only)
369 _dbus_marshal_skip_basic_type (reader->value_str,
370 current_type, reader->byte_order,
373 reader->type_pos += 1;
379 struct_reader_next (DBusTypeReader *reader,
384 base_reader_next (reader, current_type);
386 /* for STRUCT containers we return FALSE at the end of the struct,
387 * for INVALID we return FALSE at the end of the signature.
388 * In both cases we arrange for get_current_type() to return INVALID
389 * which is defined to happen iff we're at the end (no more next())
391 t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
392 if (t == DBUS_STRUCT_END_CHAR)
394 reader->type_pos += 1;
395 reader->finished = TRUE;
400 array_types_only_reader_next (DBusTypeReader *reader,
403 /* We have one "element" to be iterated over
404 * in each array, which is its element type.
405 * So the finished flag indicates whether we've
406 * iterated over it yet or not.
408 reader->finished = TRUE;
412 array_reader_next (DBusTypeReader *reader,
415 /* Skip one array element */
418 end_pos = reader->u.array.start_pos + array_reader_get_array_len (reader);
420 _dbus_assert (reader->value_pos < end_pos);
421 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
423 switch (first_type_in_signature (reader->type_str,
426 case DBUS_TYPE_STRUCT:
427 case DBUS_TYPE_VARIANT:
431 /* Recurse into the struct or variant */
432 _dbus_type_reader_recurse (reader, &sub);
434 /* Skip everything in this element */
435 while (_dbus_type_reader_next (&sub))
440 /* Now we are at the end of this element */
441 reader->value_pos = sub.value_pos;
445 case DBUS_TYPE_ARRAY:
447 _dbus_marshal_skip_array (reader->value_str, reader->byte_order,
448 first_type_in_signature (reader->type_str,
449 reader->type_pos + 1),
456 _dbus_marshal_skip_basic_type (reader->value_str,
457 current_type, reader->byte_order,
463 _dbus_assert (reader->value_pos <= end_pos);
465 if (reader->value_pos == end_pos)
467 skip_one_complete_type (reader->type_str,
473 array_init_from_mark (DBusTypeReader *reader,
474 const DBusTypeMark *mark)
476 /* Fill in the array-specific fields from the mark. The general
477 * fields are already filled in.
479 reader->u.array.start_pos = mark->array_start_pos;
480 reader->array_len_offset = mark->array_len_offset;
483 static const DBusTypeReaderClass body_reader_class = {
486 NULL, /* body is always toplevel, so doesn't get recursed into */
487 base_reader_get_current_type,
492 static const DBusTypeReaderClass body_types_only_reader_class = {
495 NULL, /* body is always toplevel, so doesn't get recursed into */
496 base_reader_get_current_type,
501 static const DBusTypeReaderClass struct_reader_class = {
504 struct_reader_recurse,
505 struct_reader_get_current_type,
510 static const DBusTypeReaderClass struct_types_only_reader_class = {
513 struct_types_only_reader_recurse,
514 struct_reader_get_current_type,
519 static const DBusTypeReaderClass array_reader_class = {
522 array_reader_recurse,
523 array_reader_get_current_type,
528 static const DBusTypeReaderClass array_types_only_reader_class = {
531 array_types_only_reader_recurse,
532 array_types_only_reader_get_current_type,
533 array_types_only_reader_next,
537 static const DBusTypeReaderClass variant_reader_class = {
540 variant_reader_recurse,
541 base_reader_get_current_type,
546 static const DBusTypeReaderClass const *
547 all_reader_classes[] = {
549 &body_types_only_reader_class,
550 &struct_reader_class,
551 &struct_types_only_reader_class,
553 &array_types_only_reader_class,
554 &variant_reader_class
558 _dbus_type_reader_init (DBusTypeReader *reader,
560 const DBusString *type_str,
562 const DBusString *value_str,
565 reader->klass = &body_reader_class;
567 reader_init (reader, byte_order, type_str, type_pos,
568 value_str, value_pos);
570 #if RECURSIVE_MARSHAL_TRACE
571 _dbus_verbose (" type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
572 reader, reader->type_pos, reader->value_pos,
573 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
578 _dbus_type_reader_init_from_mark (DBusTypeReader *reader,
580 const DBusString *type_str,
581 const DBusString *value_str,
582 const DBusTypeMark *mark)
584 reader->klass = all_reader_classes[mark->container_type];
586 reader_init (reader, byte_order,
587 mark->type_pos_in_value_str ? value_str : type_str,
589 value_str, mark->value_pos);
591 if (reader->klass->init_from_mark)
592 (* reader->klass->init_from_mark) (reader, mark);
594 #if RECURSIVE_MARSHAL_TRACE
595 _dbus_verbose (" type reader %p init from mark type_pos = %d value_pos = %d remaining sig '%s'\n",
596 reader, reader->type_pos, reader->value_pos,
597 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
602 _dbus_type_reader_init_types_only (DBusTypeReader *reader,
603 const DBusString *type_str,
606 reader->klass = &body_types_only_reader_class;
608 reader_init (reader, DBUS_COMPILER_BYTE_ORDER /* irrelevant */,
609 type_str, type_pos, NULL, _DBUS_INT_MAX /* crashes if we screw up */);
611 #if RECURSIVE_MARSHAL_TRACE
612 _dbus_verbose (" type reader %p init types only type_pos = %d remaining sig '%s'\n",
613 reader, reader->type_pos,
614 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
619 _dbus_type_reader_init_types_only_from_mark (DBusTypeReader *reader,
620 const DBusString *type_str,
621 const DBusTypeMark *mark)
623 reader->klass = all_reader_classes[mark->container_type];
624 _dbus_assert (reader->klass->types_only);
625 _dbus_assert (!mark->type_pos_in_value_str);
627 reader_init (reader, DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
628 type_str, mark->type_pos,
629 NULL, _DBUS_INT_MAX /* crashes if we screw up */);
631 if (reader->klass->init_from_mark)
632 (* reader->klass->init_from_mark) (reader, mark);
634 #if RECURSIVE_MARSHAL_TRACE
635 _dbus_verbose (" type reader %p init types only from mark type_pos = %d remaining sig '%s'\n",
636 reader, reader->type_pos,
637 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
642 _dbus_type_reader_save_mark (DBusTypeReader *reader,
645 mark->type_pos_in_value_str = (reader->type_str == reader->value_str);
646 mark->container_type = reader->klass->id;
647 _dbus_assert (all_reader_classes[reader->klass->id] == reader->klass);
649 mark->type_pos = reader->type_pos;
650 mark->value_pos = reader->value_pos;
652 /* these are just junk if the reader isn't really an array of course */
653 mark->array_len_offset = reader->array_len_offset;
654 mark->array_start_pos = reader->u.array.start_pos;
658 _dbus_type_reader_get_current_type (DBusTypeReader *reader)
662 t = (* reader->klass->get_current_type) (reader);
664 _dbus_assert (t != DBUS_STRUCT_END_CHAR);
665 _dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR);
668 _dbus_verbose (" type reader %p current type_pos = %d type = %s\n",
669 reader, reader->type_pos,
670 _dbus_type_to_string (t));
677 _dbus_type_reader_array_is_empty (DBusTypeReader *reader)
679 dbus_uint32_t array_len;
681 _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY);
682 _dbus_assert (!reader->klass->types_only);
684 /* reader is supposed to be at an array child */
685 #if RECURSIVE_MARSHAL_TRACE
686 _dbus_verbose ("checking array len at %d\n", reader->value_pos);
689 _dbus_demarshal_basic_type (reader->value_str,
695 #if RECURSIVE_MARSHAL_TRACE
696 _dbus_verbose (" ... array len = %d\n", array_len);
699 return array_len == 0;
703 _dbus_type_reader_read_basic (DBusTypeReader *reader,
708 _dbus_assert (!reader->klass->types_only);
710 t = _dbus_type_reader_get_current_type (reader);
712 _dbus_demarshal_basic_type (reader->value_str,
715 reader->value_pos, NULL);
718 #if RECURSIVE_MARSHAL_TRACE
719 _dbus_verbose (" type reader %p read basic type_pos = %d value_pos = %d remaining sig '%s'\n",
720 reader, reader->type_pos, reader->value_pos,
721 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
726 _dbus_type_reader_read_array_of_basic (DBusTypeReader *reader,
731 _dbus_assert (!reader->klass->types_only);
736 * Initialize a new reader pointing to the first type and
737 * corresponding value that's a child of the current container. It's
738 * an error to call this if the current type is a non-container.
740 * Note that DBusTypeReader traverses values, not types. So if you
741 * have an empty array of array of int, you can't recurse into it. You
742 * can only recurse into each element.
744 * @param reader the reader
745 * @param sub a reader to init pointing to the first child
748 _dbus_type_reader_recurse (DBusTypeReader *reader,
753 t = first_type_in_signature (reader->type_str, reader->type_pos);
757 case DBUS_TYPE_STRUCT:
758 if (reader->klass->types_only)
759 sub->klass = &struct_types_only_reader_class;
761 sub->klass = &struct_reader_class;
763 case DBUS_TYPE_ARRAY:
764 if (reader->klass->types_only)
765 sub->klass = &array_types_only_reader_class;
767 sub->klass = &array_reader_class;
769 case DBUS_TYPE_VARIANT:
770 if (reader->klass->types_only)
771 _dbus_assert_not_reached ("can't recurse into variant typecode");
773 sub->klass = &variant_reader_class;
776 _dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t));
777 #ifndef DBUS_DISABLE_CHECKS
778 if (t == DBUS_TYPE_INVALID)
779 _dbus_warn ("You can't recurse into an empty array or off the end of a message body\n");
780 #endif /* DBUS_DISABLE_CHECKS */
782 _dbus_assert_not_reached ("don't yet handle recursing into this type");
785 _dbus_assert (sub->klass == all_reader_classes[sub->klass->id]);
787 (* sub->klass->recurse) (sub, reader);
789 #if RECURSIVE_MARSHAL_TRACE
790 _dbus_verbose (" type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
791 sub, sub->type_pos, sub->value_pos,
792 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
797 * Skip to the next value on this "level". e.g. the next field in a
798 * struct, the next value in an array, the next key or value in a
799 * dict. Returns FALSE at the end of the current container.
801 * @param reader the reader
802 * @returns FALSE if nothing more to read at or below this level
805 _dbus_type_reader_next (DBusTypeReader *reader)
809 t = _dbus_type_reader_get_current_type (reader);
811 #if RECURSIVE_MARSHAL_TRACE
812 _dbus_verbose (" type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
813 reader, reader->type_pos, reader->value_pos,
814 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
815 _dbus_type_to_string (t));
818 if (t == DBUS_TYPE_INVALID)
821 (* reader->klass->next) (reader, t);
823 #if RECURSIVE_MARSHAL_TRACE
824 _dbus_verbose (" type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
825 reader, reader->type_pos, reader->value_pos,
826 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
827 _dbus_type_to_string (_dbus_type_reader_get_current_type (reader)));
830 return _dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID;
844 _dbus_type_writer_init (DBusTypeWriter *writer,
846 DBusString *type_str,
848 DBusString *value_str,
851 writer->byte_order = byte_order;
852 writer->type_str = type_str;
853 writer->type_pos = type_pos;
854 writer->value_str = value_str;
855 writer->value_pos = value_pos;
856 writer->container_type = DBUS_TYPE_INVALID;
857 writer->type_pos_is_expectation = FALSE;
859 #if RECURSIVE_MARSHAL_TRACE
860 _dbus_verbose ("writer %p init remaining sig '%s'\n", writer,
861 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
866 _dbus_type_writer_write_basic_no_typecode (DBusTypeWriter *writer,
870 return _dbus_marshal_basic_type (writer->value_str,
878 /* If our parent is an array, things are a little bit complicated.
880 * The parent must have a complete element type, such as
881 * "i" or "aai" or "(ii)" or "a(ii)". There can't be
882 * unclosed parens, or an "a" with no following type.
884 * To recurse, the only allowed operation is to recurse into the
885 * first type in the element type. So for "i" you can't recurse, for
886 * "ai" you can recurse into the array, for "(ii)" you can recurse
889 * If you recurse into the array for "ai", then you must specify
890 * "i" for the element type of the array you recurse into.
892 * While inside an array at any level, we need to avoid writing to
893 * type_str, since the type only appears once for the whole array,
894 * it does not appear for each array element.
896 * While inside an array type_pos points to the expected next
897 * typecode, rather than the next place we could write a typecode.
900 writer_recurse_init_and_check (DBusTypeWriter *writer,
904 _dbus_type_writer_init (sub,
911 sub->container_type = container_type;
913 if (writer->type_pos_is_expectation ||
914 (sub->container_type == DBUS_TYPE_ARRAY || sub->container_type == DBUS_TYPE_VARIANT))
915 sub->type_pos_is_expectation = TRUE;
917 sub->type_pos_is_expectation = FALSE;
919 #ifndef DBUS_DISABLE_CHECKS
920 if (writer->type_pos_is_expectation)
924 expected = first_type_in_signature (writer->type_str, writer->type_pos);
926 if (expected != sub->container_type)
928 _dbus_warn ("Writing an element of type %s, but the expected type here is %s\n",
929 _dbus_type_to_string (sub->container_type),
930 _dbus_type_to_string (expected));
931 _dbus_assert_not_reached ("bad array element or variant content written");
934 #endif /* DBUS_DISABLE_CHECKS */
936 #if RECURSIVE_MARSHAL_TRACE
937 _dbus_verbose (" type writer %p recurse parent %s type_pos = %d value_pos = %d is_expectation = %d remaining sig '%s'\n",
939 _dbus_type_to_string (writer->container_type),
940 writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
941 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
942 _dbus_verbose (" type writer %p recurse sub %s type_pos = %d value_pos = %d is_expectation = %d\n",
944 _dbus_type_to_string (sub->container_type),
945 sub->type_pos, sub->value_pos,
946 sub->type_pos_is_expectation);
951 write_or_verify_typecode (DBusTypeWriter *writer,
954 /* A subwriter inside an array or variant will have type_pos
955 * pointing to the expected typecode; a writer not inside an array
956 * or variant has type_pos pointing to the next place to insert a
959 #if RECURSIVE_MARSHAL_TRACE
960 _dbus_verbose (" type writer %p write_or_verify start type_pos = %d remaining sig '%s'\n",
961 writer, writer->type_pos,
962 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
965 if (writer->type_pos_is_expectation)
967 #ifndef DBUS_DISABLE_CHECKS
971 expected = _dbus_string_get_byte (writer->type_str, writer->type_pos);
973 if (expected != typecode)
975 _dbus_warn ("Array or variant type requires that type %s be written, but %s was written\n",
976 _dbus_type_to_string (expected), _dbus_type_to_string (typecode));
977 _dbus_assert_not_reached ("bad type inserted somewhere inside an array or variant");
980 #endif /* DBUS_DISABLE_CHECKS */
982 /* if immediately inside an array we'd always be appending an element,
983 * so the expected type doesn't change; if inside a struct or something
984 * below an array, we need to move through said struct or something.
986 if (writer->container_type != DBUS_TYPE_ARRAY)
987 writer->type_pos += 1;
991 if (!_dbus_string_insert_byte (writer->type_str,
996 writer->type_pos += 1;
999 #if RECURSIVE_MARSHAL_TRACE
1000 _dbus_verbose (" type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
1001 writer, writer->type_pos,
1002 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
1009 _dbus_type_writer_recurse_struct (DBusTypeWriter *writer,
1010 DBusTypeWriter *sub)
1012 writer_recurse_init_and_check (writer, DBUS_TYPE_STRUCT, sub);
1014 /* Ensure that we'll be able to add alignment padding and the typecode */
1015 if (!_dbus_string_alloc_space (sub->value_str, 8))
1018 if (!_dbus_string_alloc_space (sub->type_str, 1))
1021 if (!write_or_verify_typecode (sub, DBUS_STRUCT_BEGIN_CHAR))
1022 _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
1024 if (!_dbus_string_insert_bytes (sub->value_str,
1026 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
1028 _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
1029 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
1035 _dbus_type_writer_recurse_array (DBusTypeWriter *writer,
1036 const char *element_type,
1037 DBusTypeWriter *sub)
1039 int element_type_len;
1040 DBusString element_type_str;
1041 dbus_uint32_t value = 0;
1046 writer_recurse_init_and_check (writer, DBUS_TYPE_ARRAY, sub);
1048 _dbus_string_init_const (&element_type_str, element_type);
1049 element_type_len = _dbus_string_get_length (&element_type_str);
1051 #ifndef DBUS_DISABLE_CHECKS
1052 if (writer->container_type == DBUS_TYPE_ARRAY)
1054 if (!_dbus_string_equal_substring (&element_type_str, 0, element_type_len,
1055 writer->type_str, writer->u.array.element_type_pos + 1))
1057 _dbus_warn ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
1059 _dbus_assert_not_reached ("incompatible type for child array");
1062 #endif /* DBUS_DISABLE_CHECKS */
1064 /* 4 bytes for the array length and 4 bytes possible padding */
1065 if (!_dbus_string_alloc_space (sub->value_str, 8))
1068 sub->type_pos += 1; /* move to point to the element type, since type_pos
1069 * should be the expected type for further writes
1071 sub->u.array.element_type_pos = sub->type_pos;
1073 if (!writer->type_pos_is_expectation)
1075 /* sub is a toplevel/outermost array so we need to write the type data */
1077 /* alloc space for array typecode, element signature, possible 7
1080 if (!_dbus_string_alloc_space (writer->type_str, 1 + element_type_len + 7))
1083 if (!_dbus_string_insert_byte (writer->type_str,
1086 _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
1088 if (!_dbus_string_copy (&element_type_str, 0,
1089 sub->type_str, sub->u.array.element_type_pos))
1090 _dbus_assert_not_reached ("should not have failed to insert array element typecodes");
1093 /* If the parent is an array, we hold type_pos pointing at the array element type;
1094 * otherwise advance it to reflect the array value we just recursed into
1096 if (writer->container_type != DBUS_TYPE_ARRAY)
1097 writer->type_pos += 1 + element_type_len;
1099 _dbus_assert (writer->type_pos_is_expectation); /* because it's an array */
1101 /* Write the length */
1102 sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
1104 if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
1106 _dbus_assert_not_reached ("should not have failed to insert array len");
1108 _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
1110 /* Write alignment padding for array elements */
1111 _dbus_string_init_const (&str, element_type);
1112 alignment = element_type_get_alignment (&str, 0);
1114 aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
1115 if (aligned != sub->value_pos)
1117 if (!_dbus_string_insert_bytes (sub->value_str,
1119 aligned - sub->value_pos,
1121 _dbus_assert_not_reached ("should not have failed to insert alignment padding");
1123 sub->value_pos = aligned;
1125 sub->u.array.start_pos = sub->value_pos;
1127 _dbus_assert (sub->u.array.start_pos == sub->value_pos);
1128 _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
1130 #if RECURSIVE_MARSHAL_TRACE
1131 _dbus_verbose (" type writer %p recurse array done remaining sig '%s' array start_pos = %d len_pos = %d\n", sub,
1132 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0),
1133 sub->u.array.start_pos, sub->u.array.len_pos);
1139 /* Variant value will normally have:
1140 * 1 byte signature length not including nul
1141 * signature typecodes (nul terminated)
1142 * padding to 8-boundary
1143 * body according to signature
1145 * The signature string can only have a single type
1146 * in it but that type may be complex/recursive.
1148 * So a typical variant type with the integer 3 will have these
1150 * 0x1 'i' '\0' [padding to 8-boundary] 0x0 0x0 0x0 0x3
1152 * For an array of 4-byte types stuffed into variants, the padding to
1153 * 8-boundary is only the 1 byte that is required for the 4-boundary
1154 * anyhow for all array elements after the first one. And for single
1155 * variants in isolation, wasting a few bytes is hardly a big deal.
1157 * The main world of hurt for writing out a variant is that the type
1158 * string is the same string as the value string. Which means
1159 * inserting to the type string will move the value_pos; and it means
1160 * that inserting to the type string could break type alignment.
1162 * This type alignment issue is why the body of the variant is always
1163 * 8-aligned. Then we know that re-8-aligning the start of the body
1164 * will always correctly align the full contents of the variant type.
1167 _dbus_type_writer_recurse_variant (DBusTypeWriter *writer,
1168 const char *contained_type,
1169 DBusTypeWriter *sub)
1171 int contained_type_len;
1172 DBusString contained_type_str;
1174 writer_recurse_init_and_check (writer, DBUS_TYPE_VARIANT, sub);
1176 _dbus_string_init_const (&contained_type_str, contained_type);
1178 contained_type_len = _dbus_string_get_length (&contained_type_str);
1180 /* Allocate space for the worst case, which is 1 byte sig
1181 * length, nul byte at end of sig, and 7 bytes padding to
1184 if (!_dbus_string_alloc_space (sub->value_str, contained_type_len + 9))
1187 /* write VARIANT typecode to the parent's type string */
1188 if (!write_or_verify_typecode (writer, DBUS_TYPE_VARIANT))
1191 if (!_dbus_string_insert_byte (sub->value_str,
1193 contained_type_len))
1194 _dbus_assert_not_reached ("should not have failed to insert variant type sig len");
1196 sub->value_pos += 1;
1198 /* Here we switch over to the expected type sig we're about to write */
1199 sub->type_str = sub->value_str;
1200 sub->type_pos = sub->value_pos;
1202 if (!_dbus_string_copy (&contained_type_str, 0,
1203 sub->value_str, sub->value_pos))
1204 _dbus_assert_not_reached ("should not have failed to insert variant type sig");
1206 sub->value_pos += contained_type_len;
1208 if (!_dbus_string_insert_byte (sub->value_str,
1211 _dbus_assert_not_reached ("should not have failed to insert variant type nul termination");
1213 sub->value_pos += 1;
1215 if (!_dbus_string_insert_bytes (sub->value_str,
1217 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
1219 _dbus_assert_not_reached ("should not have failed to insert alignment padding for variant body");
1220 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
1226 _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
1227 DBusTypeWriter *sub)
1229 _dbus_assert (sub->type_pos > 0); /* can't be recursed if this fails */
1231 /* type_pos_is_expectation never gets unset once set, or we'd get all hosed */
1232 _dbus_assert (!writer->type_pos_is_expectation ||
1233 (writer->type_pos_is_expectation && sub->type_pos_is_expectation));
1235 #if RECURSIVE_MARSHAL_TRACE
1236 _dbus_verbose (" type writer %p unrecurse type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
1237 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
1238 _dbus_type_to_string (writer->container_type));
1239 _dbus_verbose (" type writer %p unrecurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
1240 sub, sub->type_pos, sub->value_pos,
1241 sub->type_pos_is_expectation,
1242 _dbus_type_to_string (sub->container_type));
1245 if (sub->container_type == DBUS_TYPE_STRUCT)
1247 if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
1250 else if (sub->container_type == DBUS_TYPE_ARRAY)
1254 /* Set the array length */
1255 len = sub->value_pos - sub->u.array.start_pos;
1256 _dbus_marshal_set_uint32 (sub->value_str,
1258 sub->u.array.len_pos,
1260 #if RECURSIVE_MARSHAL_TRACE
1261 _dbus_verbose (" filled in sub array len to %u at len_pos %d\n",
1262 len, sub->u.array.len_pos);
1266 /* Now get type_pos right for the parent writer. Here are the cases:
1268 * Cases !writer->type_pos_is_expectation:
1269 * (in these cases we want to update to the new insertion point)
1271 * - if we recursed into a STRUCT then we didn't know in advance
1272 * what the types in the struct would be; so we have to fill in
1273 * that information now.
1274 * writer->type_pos = sub->type_pos
1276 * - if we recursed into anything else, we knew the full array
1277 * type, or knew the single typecode marking VARIANT, so
1278 * writer->type_pos is already correct.
1279 * writer->type_pos should remain as-is
1281 * - note that the parent is never an ARRAY or VARIANT, if it were
1282 * then type_pos_is_expectation would be TRUE. The parent
1283 * is thus known to be a toplevel or STRUCT.
1285 * Cases where writer->type_pos_is_expectation:
1286 * (in these cases we want to update to next expected type to write)
1288 * - we recursed from STRUCT into STRUCT and we didn't increment
1289 * type_pos in the parent just to stay consistent with the
1290 * !writer->type_pos_is_expectation case (though we could
1291 * special-case this in recurse_struct instead if we wanted)
1292 * writer->type_pos = sub->type_pos
1294 * - we recursed from STRUCT into ARRAY or VARIANT and type_pos
1295 * for parent should have been incremented already
1296 * writer->type_pos should remain as-is
1298 * - we recursed from ARRAY into a sub-element, so type_pos in the
1299 * parent is the element type and should remain the element type
1300 * for the benefit of the next child element
1301 * writer->type_pos should remain as-is
1303 * - we recursed from VARIANT into its value, so type_pos in the
1304 * parent makes no difference since there's only one value
1305 * and we just finished writing it and won't use type_pos again
1306 * writer->type_pos should remain as-is
1308 if (sub->container_type == DBUS_TYPE_STRUCT &&
1309 (writer->container_type == DBUS_TYPE_STRUCT ||
1310 writer->container_type == DBUS_TYPE_INVALID))
1312 /* Advance the parent to the next struct field */
1313 writer->type_pos = sub->type_pos;
1316 writer->value_pos = sub->value_pos;
1318 #if RECURSIVE_MARSHAL_TRACE
1319 _dbus_verbose (" type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
1320 writer, writer->type_pos, writer->value_pos,
1321 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
1328 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
1334 /* First ensure that our type realloc will succeed */
1335 if (!_dbus_string_alloc_space (writer->type_str, 1))
1340 if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
1343 if (!write_or_verify_typecode (writer, type))
1344 _dbus_assert_not_reached ("failed to write typecode after prealloc");
1349 #if RECURSIVE_MARSHAL_TRACE
1350 _dbus_verbose (" type writer %p basic type_pos = %d value_pos = %d is_expectation = %d\n",
1351 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation);
1358 _dbus_type_writer_write_array (DBusTypeWriter *writer,
1367 /** @} */ /* end of DBusMarshal group */
1369 #ifdef DBUS_BUILD_TESTS
1370 #include "dbus-test.h"
1371 #include "dbus-list.h"
1377 DBusString signature;
1388 data_block_init (DataBlock *block)
1390 if (!_dbus_string_init (&block->signature))
1393 if (!_dbus_string_init (&block->body))
1395 _dbus_string_free (&block->signature);
1403 data_block_free (DataBlock *block)
1405 _dbus_string_free (&block->signature);
1406 _dbus_string_free (&block->body);
1410 data_block_save (DataBlock *block,
1411 DataBlockState *state)
1413 state->saved_sig_len = _dbus_string_get_length (&block->signature);
1414 state->saved_body_len = _dbus_string_get_length (&block->body);
1418 data_block_restore (DataBlock *block,
1419 DataBlockState *state)
1421 /* These set_length should be shortening things so should always work */
1423 if (!_dbus_string_set_length (&block->signature,
1424 state->saved_sig_len))
1425 _dbus_assert_not_reached ("could not restore signature length");
1427 if (!_dbus_string_set_length (&block->body,
1428 state->saved_body_len))
1429 _dbus_assert_not_reached ("could not restore body length");
1433 data_block_init_reader_writer (DataBlock *block,
1435 DBusTypeReader *reader,
1436 DBusTypeWriter *writer)
1438 _dbus_type_reader_init (reader,
1441 _dbus_string_get_length (&block->signature),
1443 _dbus_string_get_length (&block->body));
1445 _dbus_type_writer_init (writer,
1448 _dbus_string_get_length (&block->signature),
1450 _dbus_string_get_length (&block->body));
1454 real_check_expected_type (DBusTypeReader *reader,
1456 const char *funcname,
1461 t = _dbus_type_reader_get_current_type (reader);
1465 _dbus_warn ("Read type %s while expecting %s at %s line %d\n",
1466 _dbus_type_to_string (t),
1467 _dbus_type_to_string (expected),
1474 #define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__)
1476 #define NEXT_EXPECTING_TRUE(reader) do { if (!_dbus_type_reader_next (reader)) \
1478 _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d\n", \
1479 _DBUS_FUNCTION_NAME, __LINE__); \
1480 _dbus_assert_not_reached ("test failed"); \
1484 #define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader)) \
1486 _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d\n", \
1487 _DBUS_FUNCTION_NAME, __LINE__); \
1488 _dbus_assert_not_reached ("test failed"); \
1490 check_expected_type (reader, DBUS_TYPE_INVALID); \
1493 #define SAMPLE_INT32 12345678
1494 #define SAMPLE_INT32_ALTERNATE 53781429
1496 typedef struct TestTypeNode TestTypeNode;
1497 typedef struct TestTypeNodeClass TestTypeNodeClass;
1498 typedef struct TestTypeNodeContainer TestTypeNodeContainer;
1499 typedef struct TestTypeNodeContainerClass TestTypeNodeContainerClass;
1503 const TestTypeNodeClass *klass;
1506 struct TestTypeNodeContainer
1512 struct TestTypeNodeClass
1518 int subclass_detail; /* a bad hack to avoid a bunch of subclass casting */
1520 dbus_bool_t (* construct) (TestTypeNode *node);
1521 void (* destroy) (TestTypeNode *node);
1523 dbus_bool_t (* write_value) (TestTypeNode *node,
1525 DBusTypeWriter *writer,
1527 dbus_bool_t (* read_value) (TestTypeNode *node,
1529 DBusTypeReader *reader,
1531 dbus_bool_t (* build_signature) (TestTypeNode *node,
1535 struct TestTypeNodeContainerClass
1537 TestTypeNodeClass base;
1540 static dbus_bool_t int32_write_value (TestTypeNode *node,
1542 DBusTypeWriter *writer,
1544 static dbus_bool_t int32_read_value (TestTypeNode *node,
1546 DBusTypeReader *reader,
1548 static dbus_bool_t int64_write_value (TestTypeNode *node,
1550 DBusTypeWriter *writer,
1552 static dbus_bool_t int64_read_value (TestTypeNode *node,
1554 DBusTypeReader *reader,
1556 static dbus_bool_t string_write_value (TestTypeNode *node,
1558 DBusTypeWriter *writer,
1560 static dbus_bool_t string_read_value (TestTypeNode *node,
1562 DBusTypeReader *reader,
1564 static dbus_bool_t bool_read_value (TestTypeNode *node,
1566 DBusTypeReader *reader,
1568 static dbus_bool_t bool_write_value (TestTypeNode *node,
1570 DBusTypeWriter *writer,
1572 static dbus_bool_t byte_read_value (TestTypeNode *node,
1574 DBusTypeReader *reader,
1576 static dbus_bool_t byte_write_value (TestTypeNode *node,
1578 DBusTypeWriter *writer,
1580 static dbus_bool_t double_read_value (TestTypeNode *node,
1582 DBusTypeReader *reader,
1584 static dbus_bool_t double_write_value (TestTypeNode *node,
1586 DBusTypeWriter *writer,
1588 static dbus_bool_t object_path_read_value (TestTypeNode *node,
1590 DBusTypeReader *reader,
1592 static dbus_bool_t object_path_write_value (TestTypeNode *node,
1594 DBusTypeWriter *writer,
1596 static dbus_bool_t signature_read_value (TestTypeNode *node,
1598 DBusTypeReader *reader,
1600 static dbus_bool_t signature_write_value (TestTypeNode *node,
1602 DBusTypeWriter *writer,
1604 static dbus_bool_t struct_write_value (TestTypeNode *node,
1606 DBusTypeWriter *writer,
1608 static dbus_bool_t struct_read_value (TestTypeNode *node,
1610 DBusTypeReader *reader,
1612 static dbus_bool_t struct_build_signature (TestTypeNode *node,
1614 static dbus_bool_t array_write_value (TestTypeNode *node,
1616 DBusTypeWriter *writer,
1618 static dbus_bool_t array_read_value (TestTypeNode *node,
1620 DBusTypeReader *reader,
1622 static dbus_bool_t array_build_signature (TestTypeNode *node,
1624 static dbus_bool_t variant_write_value (TestTypeNode *node,
1626 DBusTypeWriter *writer,
1628 static dbus_bool_t variant_read_value (TestTypeNode *node,
1630 DBusTypeReader *reader,
1632 static void container_destroy (TestTypeNode *node);
1635 static const TestTypeNodeClass int32_class = {
1637 sizeof (TestTypeNode),
1646 static const TestTypeNodeClass uint32_class = {
1648 sizeof (TestTypeNode),
1652 int32_write_value, /* recycle from int32 */
1653 int32_read_value, /* recycle from int32 */
1657 static const TestTypeNodeClass int64_class = {
1659 sizeof (TestTypeNode),
1668 static const TestTypeNodeClass uint64_class = {
1670 sizeof (TestTypeNode),
1674 int64_write_value, /* recycle from int64 */
1675 int64_read_value, /* recycle from int64 */
1679 static const TestTypeNodeClass string_0_class = {
1681 sizeof (TestTypeNode),
1682 0, /* string length */
1690 static const TestTypeNodeClass string_1_class = {
1692 sizeof (TestTypeNode),
1693 1, /* string length */
1701 /* with nul, a len 3 string should fill 4 bytes and thus is "special" */
1702 static const TestTypeNodeClass string_3_class = {
1704 sizeof (TestTypeNode),
1705 3, /* string length */
1713 /* with nul, a len 8 string should fill 9 bytes and thus is "special" (far-fetched I suppose) */
1714 static const TestTypeNodeClass string_8_class = {
1716 sizeof (TestTypeNode),
1717 8, /* string length */
1725 static const TestTypeNodeClass bool_class = {
1727 sizeof (TestTypeNode),
1736 static const TestTypeNodeClass byte_class = {
1738 sizeof (TestTypeNode),
1747 static const TestTypeNodeClass double_class = {
1749 sizeof (TestTypeNode),
1758 static const TestTypeNodeClass object_path_class = {
1759 DBUS_TYPE_OBJECT_PATH,
1760 sizeof (TestTypeNode),
1764 object_path_write_value,
1765 object_path_read_value,
1769 static const TestTypeNodeClass signature_class = {
1770 DBUS_TYPE_SIGNATURE,
1771 sizeof (TestTypeNode),
1775 signature_write_value,
1776 signature_read_value,
1780 static const TestTypeNodeClass struct_1_class = {
1782 sizeof (TestTypeNodeContainer),
1783 1, /* number of times children appear as fields */
1788 struct_build_signature
1791 static const TestTypeNodeClass struct_2_class = {
1793 sizeof (TestTypeNodeContainer),
1794 2, /* number of times children appear as fields */
1799 struct_build_signature
1802 static const TestTypeNodeClass array_0_class = {
1804 sizeof (TestTypeNodeContainer),
1805 0, /* number of array elements */
1810 array_build_signature
1813 static const TestTypeNodeClass array_1_class = {
1815 sizeof (TestTypeNodeContainer),
1816 1, /* number of array elements */
1821 array_build_signature
1824 static const TestTypeNodeClass array_2_class = {
1826 sizeof (TestTypeNodeContainer),
1827 2, /* number of array elements */
1832 array_build_signature
1835 static const TestTypeNodeClass array_9_class = {
1837 sizeof (TestTypeNodeContainer),
1838 9, /* number of array elements */
1843 array_build_signature
1846 static const TestTypeNodeClass variant_class = {
1848 sizeof (TestTypeNodeContainer),
1852 variant_write_value,
1857 static const TestTypeNodeClass* const
1873 #define N_BASICS (_DBUS_N_ELEMENTS (basic_nodes))
1875 static const TestTypeNodeClass* const
1876 container_nodes[] = {
1883 /* array_9_class is omitted on purpose, it's too slow;
1884 * we only use it in one hardcoded test below
1887 #define N_CONTAINERS (_DBUS_N_ELEMENTS (container_nodes))
1889 static TestTypeNode*
1890 node_new (const TestTypeNodeClass *klass)
1894 node = dbus_malloc0 (klass->instance_size);
1898 node->klass = klass;
1900 if (klass->construct)
1902 if (!(* klass->construct) (node))
1913 node_destroy (TestTypeNode *node)
1915 if (node->klass->destroy)
1916 (* node->klass->destroy) (node);
1921 node_write_value (TestTypeNode *node,
1923 DBusTypeWriter *writer,
1926 return (* node->klass->write_value) (node, block, writer, seed);
1930 node_read_value (TestTypeNode *node,
1932 DBusTypeReader *reader,
1936 DBusTypeReader restored;
1938 _dbus_type_reader_save_mark (reader, &mark);
1940 if (!(* node->klass->read_value) (node, block, reader, seed))
1943 _dbus_type_reader_init_from_mark (&restored,
1944 reader->byte_order, /* a bit of a cheat,
1945 * since we didn't bother
1946 * to store this in DataBlock
1952 if (!(* node->klass->read_value) (node, block, &restored, seed))
1959 node_build_signature (TestTypeNode *node,
1962 if (node->klass->build_signature)
1963 return (* node->klass->build_signature) (node, str);
1965 return _dbus_string_append_byte (str, node->klass->typecode);
1969 node_append_child (TestTypeNode *node,
1970 TestTypeNode *child)
1972 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
1974 _dbus_assert (node->klass->instance_size >= (int) sizeof (TestTypeNodeContainer));
1976 if (!_dbus_list_append (&container->children, child))
1977 _dbus_assert_not_reached ("no memory"); /* we never check the return value on node_append_child anyhow - it's run from outside the malloc-failure test code */
1984 const DBusString *signature;
1988 TestTypeNode **nodes;
1990 } NodeIterationData;
1993 run_test_nodes_iteration (void *data)
1995 NodeIterationData *nid = data;
1996 DBusTypeReader reader;
1997 DBusTypeWriter writer;
2001 * 1. write the value
2002 * 2. strcmp-compare with the signature we built
2004 * 4. type-iterate the signature and the value and see if they are the same type-wise
2006 data_block_init_reader_writer (nid->block,
2011 while (i < nid->n_nodes)
2013 if (!node_write_value (nid->nodes[i], nid->block, &writer, i))
2019 if (!_dbus_string_equal_substring (nid->signature, 0, _dbus_string_get_length (nid->signature),
2020 &nid->block->signature, nid->type_offset))
2022 _dbus_warn ("Expected signature '%s' and got '%s' with initial offset %d\n",
2023 _dbus_string_get_const_data (nid->signature),
2024 _dbus_string_get_const_data_len (&nid->block->signature, nid->type_offset, 0),
2026 _dbus_assert_not_reached ("wrong signature");
2030 while (i < nid->n_nodes)
2032 if (!node_read_value (nid->nodes[i], nid->block, &reader, i))
2035 if (i + 1 == nid->n_nodes)
2036 NEXT_EXPECTING_FALSE (&reader);
2038 NEXT_EXPECTING_TRUE (&reader);
2043 /* FIXME type-iterate both signature and value and compare the resulting
2044 * tree to the node tree
2051 run_test_nodes_in_one_configuration (TestTypeNode **nodes,
2053 const DBusString *signature,
2058 NodeIterationData nid;
2060 if (!data_block_init (&block))
2061 _dbus_assert_not_reached ("no memory");
2063 if (!_dbus_string_lengthen (&block.signature, initial_offset))
2064 _dbus_assert_not_reached ("no memory");
2066 if (!_dbus_string_lengthen (&block.body, initial_offset))
2067 _dbus_assert_not_reached ("no memory");
2069 nid.signature = signature;
2071 nid.type_offset = initial_offset;
2073 nid.n_nodes = n_nodes;
2074 nid.byte_order = byte_order;
2076 /* FIXME put the OOM testing back once we debug everything and are willing to
2077 * wait for it to run ;-)
2080 _dbus_test_oom_handling ("running test node",
2081 run_test_nodes_iteration,
2084 if (!run_test_nodes_iteration (&nid))
2085 _dbus_assert_not_reached ("no memory");
2088 data_block_free (&block);
2092 run_test_nodes (TestTypeNode **nodes,
2096 DBusString signature;
2098 if (!_dbus_string_init (&signature))
2099 _dbus_assert_not_reached ("no memory");
2104 if (! node_build_signature (nodes[i], &signature))
2105 _dbus_assert_not_reached ("no memory");
2110 _dbus_verbose (">>> test nodes with signature '%s'\n",
2111 _dbus_string_get_const_data (&signature));
2113 /* We do start offset 0 through 9, to get various alignment cases. Still this
2114 * obviously makes the test suite run 10x as slow.
2119 run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
2120 DBUS_LITTLE_ENDIAN, i);
2121 run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
2122 DBUS_BIG_ENDIAN, i);
2127 _dbus_string_free (&signature);
2130 #define N_VALUES (N_BASICS * N_CONTAINERS + N_BASICS)
2132 static TestTypeNode*
2133 value_generator (int *ip)
2136 const TestTypeNodeClass *child_klass;
2137 const TestTypeNodeClass *container_klass;
2138 TestTypeNode *child;
2141 _dbus_assert (i <= N_VALUES);
2147 else if (i < N_BASICS)
2149 node = node_new (basic_nodes[i]);
2153 /* imagine an array:
2154 * container 0 of basic 0
2155 * container 0 of basic 1
2156 * container 0 of basic 2
2157 * container 1 of basic 0
2158 * container 1 of basic 1
2159 * container 1 of basic 2
2163 container_klass = container_nodes[i / N_BASICS];
2164 child_klass = basic_nodes[i % N_BASICS];
2166 node = node_new (container_klass);
2167 child = node_new (child_klass);
2169 node_append_child (node, child);
2172 *ip += 1; /* increment the generator */
2178 make_and_run_values_inside_container (const TestTypeNodeClass *container_klass,
2182 TestTypeNode *container;
2183 TestTypeNode *child;
2186 root = node_new (container_klass);
2188 for (i = 1; i < n_nested; i++)
2190 child = node_new (container_klass);
2191 node_append_child (container, child);
2195 /* container should now be the most-nested container */
2198 while ((child = value_generator (&i)))
2200 node_append_child (container, child);
2202 run_test_nodes (&root, 1);
2204 _dbus_list_clear (&((TestTypeNodeContainer*)container)->children);
2205 node_destroy (child);
2208 node_destroy (root);
2212 make_and_run_test_nodes (void)
2216 /* We try to do this in order of "complicatedness" so that test
2217 * failures tend to show up in the simplest test case that
2218 * demonstrates the failure. There are also some tests that run
2219 * more than once for this reason, first while going through simple
2220 * cases, second while going through a broader range of complex
2223 /* Each basic node. The basic nodes should include:
2225 * - each fixed-size type (in such a way that it has different values each time,
2226 * so we can tell if we mix two of them up)
2227 * - strings of various lengths
2231 /* Each container node. The container nodes should include:
2233 * struct with 1 and 2 copies of the contained item
2234 * array with 0, 1, 2 copies of the contained item
2237 /* Let a "value" be a basic node, or a container containing a single basic node.
2238 * Let n_values be the number of such values i.e. (n_container * n_basic + n_basic)
2239 * When iterating through all values to make combinations, do the basic types
2240 * first and the containers second.
2242 /* Each item is shown with its number of iterations to complete so
2243 * we can keep a handle on this unit test
2246 /* FIXME test just an empty body, no types at all */
2248 _dbus_verbose (">>> >>> Each value by itself %d iterations\n",
2253 while ((node = value_generator (&i)))
2255 run_test_nodes (&node, 1);
2257 node_destroy (node);
2261 _dbus_verbose (">>> >>> All values in one big toplevel 1 iteration\n");
2263 TestTypeNode *nodes[N_VALUES];
2266 while ((nodes[i] = value_generator (&i)))
2269 run_test_nodes (nodes, N_VALUES);
2271 for (i = 0; i < N_VALUES; i++)
2272 node_destroy (nodes[i]);
2275 _dbus_verbose (">>> >>> Each value,value pair combination as toplevel, in both orders %d iterations\n",
2276 N_VALUES * N_VALUES * 2);
2278 TestTypeNode *nodes[2];
2281 while ((nodes[0] = value_generator (&i)))
2284 while ((nodes[1] = value_generator (&j)))
2286 run_test_nodes (nodes, 2);
2288 node_destroy (nodes[1]);
2291 node_destroy (nodes[0]);
2295 _dbus_verbose (">>> >>> Each container containing each value %d iterations\n",
2296 N_CONTAINERS * N_VALUES);
2297 for (i = 0; i < N_CONTAINERS; i++)
2299 const TestTypeNodeClass *container_klass = container_nodes[i];
2301 make_and_run_values_inside_container (container_klass, 1);
2304 _dbus_verbose (">>> >>> Each container of same container of each value %d iterations\n",
2305 N_CONTAINERS * N_VALUES);
2306 for (i = 0; i < N_CONTAINERS; i++)
2308 const TestTypeNodeClass *container_klass = container_nodes[i];
2310 make_and_run_values_inside_container (container_klass, 2);
2313 _dbus_verbose (">>> >>> Each container of same container of same container of each value %d iterations\n",
2314 N_CONTAINERS * N_VALUES);
2315 for (i = 0; i < N_CONTAINERS; i++)
2317 const TestTypeNodeClass *container_klass = container_nodes[i];
2319 make_and_run_values_inside_container (container_klass, 3);
2322 _dbus_verbose (">>> >>> Each value,value pair inside a struct %d iterations\n",
2323 N_VALUES * N_VALUES);
2325 TestTypeNode *val1, *val2;
2328 node = node_new (&struct_1_class);
2331 while ((val1 = value_generator (&i)))
2334 while ((val2 = value_generator (&j)))
2336 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2338 node_append_child (node, val1);
2339 node_append_child (node, val2);
2341 run_test_nodes (&node, 1);
2343 _dbus_list_clear (&container->children);
2344 node_destroy (val2);
2346 node_destroy (val1);
2348 node_destroy (node);
2351 _dbus_verbose (">>> >>> all values in one big struct 1 iteration\n");
2354 TestTypeNode *child;
2356 node = node_new (&struct_1_class);
2359 while ((child = value_generator (&i)))
2360 node_append_child (node, child);
2362 run_test_nodes (&node, 1);
2364 node_destroy (node);
2367 _dbus_verbose (">>> >>> Each value in a large array %d iterations\n",
2373 node = node_new (&array_9_class);
2376 while ((val = value_generator (&i)))
2378 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2380 node_append_child (node, val);
2382 run_test_nodes (&node, 1);
2384 _dbus_list_clear (&container->children);
2388 node_destroy (node);
2391 _dbus_verbose (">>> >>> Each container of each container of each value %d iterations\n",
2392 N_CONTAINERS * N_CONTAINERS * N_VALUES);
2393 for (i = 0; i < N_CONTAINERS; i++)
2395 const TestTypeNodeClass *outer_container_klass = container_nodes[i];
2396 TestTypeNode *outer_container = node_new (outer_container_klass);
2398 for (j = 0; j < N_CONTAINERS; j++)
2400 TestTypeNode *child;
2401 const TestTypeNodeClass *inner_container_klass = container_nodes[j];
2402 TestTypeNode *inner_container = node_new (inner_container_klass);
2404 node_append_child (outer_container, inner_container);
2407 while ((child = value_generator (&m)))
2409 node_append_child (inner_container, child);
2411 run_test_nodes (&outer_container, 1);
2413 _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
2414 node_destroy (child);
2416 _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
2417 node_destroy (inner_container);
2419 node_destroy (outer_container);
2423 /* This one takes a really long time, so comment it out for now */
2424 _dbus_verbose (">>> >>> Each container of each container of each container of each value %d iterations\n",
2425 N_CONTAINERS * N_CONTAINERS * N_CONTAINERS * N_VALUES);
2426 for (i = 0; i < N_CONTAINERS; i++)
2428 const TestTypeNodeClass *outer_container_klass = container_nodes[i];
2429 TestTypeNode *outer_container = node_new (outer_container_klass);
2431 for (j = 0; j < N_CONTAINERS; j++)
2433 const TestTypeNodeClass *inner_container_klass = container_nodes[j];
2434 TestTypeNode *inner_container = node_new (inner_container_klass);
2436 node_append_child (outer_container, inner_container);
2438 for (k = 0; k < N_CONTAINERS; k++)
2440 TestTypeNode *child;
2441 const TestTypeNodeClass *center_container_klass = container_nodes[k];
2442 TestTypeNode *center_container = node_new (center_container_klass);
2444 node_append_child (inner_container, center_container);
2447 while ((child = value_generator (&m)))
2449 node_append_child (center_container, child);
2451 run_test_nodes (&outer_container, 1);
2453 _dbus_list_clear (&((TestTypeNodeContainer*)center_container)->children);
2454 node_destroy (child);
2456 _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
2457 node_destroy (center_container);
2459 _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
2460 node_destroy (inner_container);
2462 node_destroy (outer_container);
2464 #endif /* #if 0 expensive test */
2466 _dbus_verbose (">>> >>> Each value,value,value triplet combination as toplevel, in all orders %d iterations\n",
2467 N_VALUES * N_VALUES * N_VALUES);
2469 TestTypeNode *nodes[3];
2472 while ((nodes[0] = value_generator (&i)))
2475 while ((nodes[1] = value_generator (&j)))
2478 while ((nodes[2] = value_generator (&k)))
2480 run_test_nodes (nodes, 3);
2482 node_destroy (nodes[2]);
2484 node_destroy (nodes[1]);
2486 node_destroy (nodes[0]);
2491 dbus_bool_t _dbus_marshal_recursive_test (void);
2494 _dbus_marshal_recursive_test (void)
2496 make_and_run_test_nodes ();
2502 dbus_bool_t _dbus_marshal_test (void);
2504 main (int argc, char **argv)
2506 _dbus_marshal_test ();
2508 _dbus_marshal_recursive_test ();
2518 * Implementations of each type node class
2525 int32_from_seed (int seed)
2527 /* Generate an integer value that's predictable from seed. We could
2528 * just use seed itself, but that would only ever touch one byte of
2529 * the int so would miss some kinds of bug.
2533 v = 42; /* just to quiet compiler afaik */
2540 v = SAMPLE_INT32_ALTERNATE;
2554 v *= seed; /* wraps around eventually, which is fine */
2560 int32_write_value (TestTypeNode *node,
2562 DBusTypeWriter *writer,
2565 /* also used for uint32 */
2568 v = int32_from_seed (seed);
2570 return _dbus_type_writer_write_basic (writer,
2571 node->klass->typecode,
2576 int32_read_value (TestTypeNode *node,
2578 DBusTypeReader *reader,
2581 /* also used for uint32 */
2584 check_expected_type (reader, node->klass->typecode);
2586 _dbus_type_reader_read_basic (reader,
2587 (dbus_int32_t*) &v);
2589 _dbus_assert (v == int32_from_seed (seed));
2594 #ifdef DBUS_HAVE_INT64
2596 int64_from_seed (int seed)
2601 v32 = int32_from_seed (seed);
2603 v = - (dbus_int32_t) ~ v32;
2604 v |= (((dbus_int64_t)v32) << 32);
2611 int64_write_value (TestTypeNode *node,
2613 DBusTypeWriter *writer,
2616 #ifdef DBUS_HAVE_INT64
2617 /* also used for uint64 */
2620 v = int64_from_seed (seed);
2622 return _dbus_type_writer_write_basic (writer,
2623 node->klass->typecode,
2631 int64_read_value (TestTypeNode *node,
2633 DBusTypeReader *reader,
2636 #ifdef DBUS_HAVE_INT64
2637 /* also used for uint64 */
2640 check_expected_type (reader, node->klass->typecode);
2642 _dbus_type_reader_read_basic (reader,
2643 (dbus_int64_t*) &v);
2645 _dbus_assert (v == int64_from_seed (seed));
2653 #define MAX_SAMPLE_STRING_LEN 10
2655 string_from_seed (char *buf,
2662 _dbus_assert (len < MAX_SAMPLE_STRING_LEN);
2664 v = (unsigned char) ('A' + seed);
2669 if (v < 'A' || v > 'z')
2682 string_write_value (TestTypeNode *node,
2684 DBusTypeWriter *writer,
2687 char buf[MAX_SAMPLE_STRING_LEN];
2689 string_from_seed (buf, node->klass->subclass_detail,
2692 return _dbus_type_writer_write_basic (writer,
2693 node->klass->typecode,
2698 string_read_value (TestTypeNode *node,
2700 DBusTypeReader *reader,
2704 char buf[MAX_SAMPLE_STRING_LEN];
2706 check_expected_type (reader, node->klass->typecode);
2708 _dbus_type_reader_read_basic (reader,
2709 (const char **) &v);
2711 string_from_seed (buf, node->klass->subclass_detail,
2714 if (strcmp (buf, v) != 0)
2716 _dbus_warn ("read string '%s' expected '%s'\n",
2718 _dbus_assert_not_reached ("test failed");
2724 #define BOOL_FROM_SEED(seed) (seed % 2)
2727 bool_write_value (TestTypeNode *node,
2729 DBusTypeWriter *writer,
2734 v = BOOL_FROM_SEED (seed);
2736 return _dbus_type_writer_write_basic (writer,
2737 node->klass->typecode,
2742 bool_read_value (TestTypeNode *node,
2744 DBusTypeReader *reader,
2749 check_expected_type (reader, node->klass->typecode);
2751 _dbus_type_reader_read_basic (reader,
2752 (unsigned char*) &v);
2754 _dbus_assert (v == BOOL_FROM_SEED (seed));
2759 #define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed))
2762 byte_write_value (TestTypeNode *node,
2764 DBusTypeWriter *writer,
2769 v = BYTE_FROM_SEED (seed);
2771 return _dbus_type_writer_write_basic (writer,
2772 node->klass->typecode,
2777 byte_read_value (TestTypeNode *node,
2779 DBusTypeReader *reader,
2784 check_expected_type (reader, node->klass->typecode);
2786 _dbus_type_reader_read_basic (reader,
2787 (unsigned char*) &v);
2789 _dbus_assert (v == BYTE_FROM_SEED (seed));
2795 double_from_seed (int seed)
2797 return SAMPLE_INT32 * (double) seed + 0.3;
2801 double_write_value (TestTypeNode *node,
2803 DBusTypeWriter *writer,
2808 v = double_from_seed (seed);
2810 return _dbus_type_writer_write_basic (writer,
2811 node->klass->typecode,
2816 double_read_value (TestTypeNode *node,
2818 DBusTypeReader *reader,
2824 check_expected_type (reader, node->klass->typecode);
2826 _dbus_type_reader_read_basic (reader,
2829 expected = double_from_seed (seed);
2831 if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected))
2833 #ifdef DBUS_HAVE_INT64
2834 _dbus_warn ("Expected double %g got %g\n bits = 0x%llx vs.\n bits = 0x%llx)\n",
2836 *(dbus_uint64_t*)&expected,
2837 *(dbus_uint64_t*)&v);
2839 _dbus_assert_not_reached ("test failed");
2846 #define MAX_SAMPLE_OBJECT_PATH_LEN 10
2848 object_path_from_seed (char *buf,
2854 v = (unsigned char) ('A' + seed);
2859 if (v < 'A' || v > 'z')
2874 object_path_write_value (TestTypeNode *node,
2876 DBusTypeWriter *writer,
2879 char buf[MAX_SAMPLE_OBJECT_PATH_LEN];
2881 object_path_from_seed (buf, seed);
2883 return _dbus_type_writer_write_basic (writer,
2884 node->klass->typecode,
2889 object_path_read_value (TestTypeNode *node,
2891 DBusTypeReader *reader,
2895 char buf[MAX_SAMPLE_OBJECT_PATH_LEN];
2897 check_expected_type (reader, node->klass->typecode);
2899 _dbus_type_reader_read_basic (reader,
2900 (const char **) &v);
2902 object_path_from_seed (buf, seed);
2904 if (strcmp (buf, v) != 0)
2906 _dbus_warn ("read object path '%s' expected '%s'\n",
2908 _dbus_assert_not_reached ("test failed");
2915 #define MAX_SAMPLE_SIGNATURE_LEN 10
2917 signature_from_seed (char *buf,
2922 const char *sample_signatures[] = {
2930 s = sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)];
2932 for (i = 0; s[i]; i++)
2940 signature_write_value (TestTypeNode *node,
2942 DBusTypeWriter *writer,
2945 char buf[MAX_SAMPLE_SIGNATURE_LEN];
2947 signature_from_seed (buf, seed);
2949 return _dbus_type_writer_write_basic (writer,
2950 node->klass->typecode,
2955 signature_read_value (TestTypeNode *node,
2957 DBusTypeReader *reader,
2961 char buf[MAX_SAMPLE_SIGNATURE_LEN];
2963 check_expected_type (reader, node->klass->typecode);
2965 _dbus_type_reader_read_basic (reader,
2966 (const char **) &v);
2968 signature_from_seed (buf, seed);
2970 if (strcmp (buf, v) != 0)
2972 _dbus_warn ("read signature value '%s' expected '%s'\n",
2974 _dbus_assert_not_reached ("test failed");
2981 struct_write_value (TestTypeNode *node,
2983 DBusTypeWriter *writer,
2986 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2987 DataBlockState saved;
2992 n_copies = node->klass->subclass_detail;
2994 _dbus_assert (container->children != NULL);
2996 data_block_save (block, &saved);
2998 if (!_dbus_type_writer_recurse_struct (writer,
3003 while (i < n_copies)
3007 link = _dbus_list_get_first_link (&container->children);
3008 while (link != NULL)
3010 TestTypeNode *child = link->data;
3011 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3013 if (!node_write_value (child, block, &sub, i))
3015 data_block_restore (block, &saved);
3025 if (!_dbus_type_writer_unrecurse (writer, &sub))
3027 data_block_restore (block, &saved);
3035 struct_read_value (TestTypeNode *node,
3037 DBusTypeReader *reader,
3040 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3045 n_copies = node->klass->subclass_detail;
3047 check_expected_type (reader, DBUS_TYPE_STRUCT);
3049 _dbus_type_reader_recurse (reader, &sub);
3052 while (i < n_copies)
3056 link = _dbus_list_get_first_link (&container->children);
3057 while (link != NULL)
3059 TestTypeNode *child = link->data;
3060 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3062 if (!node_read_value (child, block, &sub, i))
3065 if (i == (n_copies - 1) && next == NULL)
3066 NEXT_EXPECTING_FALSE (&sub);
3068 NEXT_EXPECTING_TRUE (&sub);
3080 struct_build_signature (TestTypeNode *node,
3083 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3088 n_copies = node->klass->subclass_detail;
3090 orig_len = _dbus_string_get_length (str);
3092 if (!_dbus_string_append_byte (str, DBUS_STRUCT_BEGIN_CHAR))
3096 while (i < n_copies)
3100 link = _dbus_list_get_first_link (&container->children);
3101 while (link != NULL)
3103 TestTypeNode *child = link->data;
3104 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3106 if (!node_build_signature (child, str))
3115 if (!_dbus_string_append_byte (str, DBUS_STRUCT_END_CHAR))
3121 _dbus_string_set_length (str, orig_len);
3126 array_write_value (TestTypeNode *node,
3128 DBusTypeWriter *writer,
3131 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3132 DataBlockState saved;
3134 DBusString element_signature;
3138 n_copies = node->klass->subclass_detail;
3140 _dbus_assert (container->children != NULL);
3142 data_block_save (block, &saved);
3144 if (!_dbus_string_init (&element_signature))
3147 if (!node_build_signature (_dbus_list_get_first (&container->children),
3148 &element_signature))
3151 if (!_dbus_type_writer_recurse_array (writer,
3152 _dbus_string_get_const_data (&element_signature),
3157 while (i < n_copies)
3161 link = _dbus_list_get_first_link (&container->children);
3162 while (link != NULL)
3164 TestTypeNode *child = link->data;
3165 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3167 if (!node_write_value (child, block, &sub, i))
3176 if (!_dbus_type_writer_unrecurse (writer, &sub))
3179 _dbus_string_free (&element_signature);
3183 data_block_restore (block, &saved);
3184 _dbus_string_free (&element_signature);
3189 array_read_value (TestTypeNode *node,
3191 DBusTypeReader *reader,
3194 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3199 n_copies = node->klass->subclass_detail;
3201 check_expected_type (reader, DBUS_TYPE_ARRAY);
3205 _dbus_assert (!_dbus_type_reader_array_is_empty (reader));
3207 _dbus_type_reader_recurse (reader, &sub);
3210 while (i < n_copies)
3214 link = _dbus_list_get_first_link (&container->children);
3215 while (link != NULL)
3217 TestTypeNode *child = link->data;
3218 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3220 if (!node_read_value (child, block, &sub, i))
3223 if (i == (n_copies - 1) && next == NULL)
3224 NEXT_EXPECTING_FALSE (&sub);
3226 NEXT_EXPECTING_TRUE (&sub);
3236 _dbus_assert (_dbus_type_reader_array_is_empty (reader));
3243 array_build_signature (TestTypeNode *node,
3246 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3249 orig_len = _dbus_string_get_length (str);
3251 if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
3254 if (!node_build_signature (_dbus_list_get_first (&container->children),
3261 _dbus_string_set_length (str, orig_len);
3265 /* 10 is random just to add another seed that we use in the suite */
3266 #define VARIANT_SEED 10
3269 variant_write_value (TestTypeNode *node,
3271 DBusTypeWriter *writer,
3274 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3275 DataBlockState saved;
3277 DBusString content_signature;
3278 TestTypeNode *child;
3280 _dbus_assert (container->children != NULL);
3281 _dbus_assert (_dbus_list_length_is_one (&container->children));
3283 child = _dbus_list_get_first (&container->children);
3285 data_block_save (block, &saved);
3287 if (!_dbus_string_init (&content_signature))
3290 if (!node_build_signature (child,
3291 &content_signature))
3294 if (!_dbus_type_writer_recurse_variant (writer,
3295 _dbus_string_get_const_data (&content_signature),
3299 if (!node_write_value (child, block, &sub, VARIANT_SEED))
3302 if (!_dbus_type_writer_unrecurse (writer, &sub))
3305 _dbus_string_free (&content_signature);
3309 data_block_restore (block, &saved);
3310 _dbus_string_free (&content_signature);
3315 variant_read_value (TestTypeNode *node,
3317 DBusTypeReader *reader,
3320 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3322 TestTypeNode *child;
3324 _dbus_assert (container->children != NULL);
3325 _dbus_assert (_dbus_list_length_is_one (&container->children));
3327 child = _dbus_list_get_first (&container->children);
3329 check_expected_type (reader, DBUS_TYPE_VARIANT);
3331 _dbus_type_reader_recurse (reader, &sub);
3333 if (!node_read_value (child, block, &sub, VARIANT_SEED))
3336 NEXT_EXPECTING_FALSE (&sub);
3342 container_destroy (TestTypeNode *node)
3344 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3347 link = _dbus_list_get_first_link (&container->children);
3348 while (link != NULL)
3350 TestTypeNode *child = link->data;
3351 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3353 node_destroy (child);
3355 _dbus_list_free_link (link);
3361 #endif /* DBUS_BUILD_TESTS */