27#include "dbus-marshal-recursive.h"
28#include "dbus-marshal-basic.h"
29#include "dbus-signature.h"
30#include "dbus-internals.h"
45 int start_after_new_pos,
46 int start_after_new_len,
50#define RECURSIVE_MARSHAL_READ_TRACE 0
53#define RECURSIVE_MARSHAL_WRITE_TRACE 0
77apply_and_free_fixups (
DBusList **fixups,
82#if RECURSIVE_MARSHAL_WRITE_TRACE
84 _dbus_verbose (
" %d FIXUPS to apply\n",
101#if RECURSIVE_MARSHAL_WRITE_TRACE
102 _dbus_verbose (
" applying FIXUP to reader %p at pos %d new_len = %d old len %d\n",
140element_type_get_alignment (
const DBusString *str,
177struct_or_dict_entry_types_only_reader_recurse (
DBusTypeReader *sub,
180 base_reader_recurse (sub, parent);
184 _dbus_string_get_byte (sub->
type_str,
194 struct_or_dict_entry_types_only_reader_recurse (sub, parent);
204 base_reader_recurse (sub, parent);
216#define ARRAY_READER_LEN_POS(reader) \
217 ((reader)->u.array.start_pos - ((int)(reader)->array_len_offset) - 4)
227 _dbus_assert (_DBUS_ALIGN_VALUE (len_pos, 4) == (
unsigned) len_pos);
229 _dbus_string_get_const_udata_len (reader->
value_str, len_pos, 4));
231#if RECURSIVE_MARSHAL_READ_TRACE
232 _dbus_verbose (
" reader %p len_pos %d array len %u len_offset %d\n",
248 array_types_only_reader_recurse (sub, parent);
256 alignment = element_type_get_alignment (sub->
type_str,
265#if RECURSIVE_MARSHAL_READ_TRACE
266 _dbus_verbose (
" type reader %p array start = %d len_offset = %d array len = %d array element type = %s\n",
270 array_reader_get_array_len (sub),
281 int contained_alignment;
283 base_reader_recurse (sub, parent);
301#if RECURSIVE_MARSHAL_READ_TRACE
302 _dbus_verbose (
" type reader %p variant containing '%s'\n",
304 _dbus_string_get_const_data_len (sub->
type_str,
315 end_pos = reader->
u.array.
start_pos + array_reader_get_array_len (reader);
324skip_one_complete_type (
const DBusString *type_str,
343 const unsigned char *p;
344 const unsigned char *start;
349 start = (
const unsigned char *)type_str;
350 p = start + *type_pos;
420 *type_pos = (int) (p - start);
424find_len_of_complete_type (
const DBusString *type_str,
431 skip_one_complete_type (type_str, &end);
433 return end - type_pos;
440 switch (current_type)
507 base_reader_next (reader, current_type);
528 base_reader_next (reader, current_type);
562 end_pos = reader->
u.array.
start_pos + array_reader_get_array_len (reader);
564#if RECURSIVE_MARSHAL_READ_TRACE
565 _dbus_verbose (
" reader %p array next START start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
617#if RECURSIVE_MARSHAL_READ_TRACE
618 _dbus_verbose (
" reader %p array next END start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
629 skip_one_complete_type (reader->
type_str,
653 struct_or_dict_entry_reader_recurse,
661 struct_or_dict_entry_types_only_reader_recurse,
669 struct_or_dict_entry_reader_recurse,
671 dict_entry_reader_next
675 "dict_entry types", 5,
677 struct_or_dict_entry_types_only_reader_recurse,
679 dict_entry_reader_next
685 array_reader_recurse,
686 array_reader_check_finished,
693 array_types_only_reader_recurse,
695 array_types_only_reader_next
701 variant_reader_recurse,
706#ifndef DBUS_DISABLE_ASSERT
708all_reader_classes[] = {
710 &body_types_only_reader_class,
711 &struct_reader_class,
712 &struct_types_only_reader_class,
713 &dict_entry_reader_class,
714 &dict_entry_types_only_reader_class,
716 &array_types_only_reader_class,
717 &variant_reader_class
739 reader_init (reader, byte_order, type_str, type_pos,
740 value_str, value_pos);
742 reader->
klass = &body_reader_class;
744#if RECURSIVE_MARSHAL_READ_TRACE
745 _dbus_verbose (
" type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
764 reader_init (reader, DBUS_COMPILER_BYTE_ORDER ,
767 reader->
klass = &body_types_only_reader_class;
769#if RECURSIVE_MARSHAL_READ_TRACE
770 _dbus_verbose (
" type reader %p init types only type_pos = %d remaining sig '%s'\n",
803 _dbus_verbose (
" type reader %p current type_pos = %d type = %s\n",
853 const unsigned char **value_location)
857 *value_location = _dbus_string_get_const_udata_len (reader->
value_str,
885#if RECURSIVE_MARSHAL_READ_TRACE
886 _dbus_verbose (
" type reader %p read basic type_pos = %d value_pos = %d remaining sig '%s'\n",
904 return array_reader_get_array_len (reader);
946 total_len = array_reader_get_array_len (reader);
947 end_pos = reader->
u.array.
start_pos + total_len;
948 remaining_len = end_pos - reader->
value_pos;
950#if RECURSIVE_MARSHAL_READ_TRACE
951 _dbus_verbose (
"end_pos %d total_len %d remaining_len %d value_pos %d\n",
952 end_pos, total_len, remaining_len, reader->
value_pos);
957 if (remaining_len == 0)
960 *value = _dbus_string_get_const_data_len (reader->
value_str,
964 *n_elements = remaining_len / alignment;
967#if RECURSIVE_MARSHAL_READ_TRACE
968 _dbus_verbose (
" type reader %p read fixed array type_pos = %d value_pos = %d remaining sig '%s'\n",
999 klass = &struct_types_only_reader_class;
1001 klass = &struct_reader_class;
1005 klass = &dict_entry_types_only_reader_class;
1007 klass = &dict_entry_reader_class;
1011 klass = &array_types_only_reader_class;
1013 klass = &array_reader_class;
1019 klass = &variant_reader_class;
1023#ifndef DBUS_DISABLE_CHECKS
1034 (* klass->
recurse) (sub, reader);
1037#if RECURSIVE_MARSHAL_READ_TRACE
1038 _dbus_verbose (
" type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
1059#if RECURSIVE_MARSHAL_READ_TRACE
1060 _dbus_verbose (
" type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
1071#if RECURSIVE_MARSHAL_READ_TRACE
1072 _dbus_verbose (
" type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
1174 orig_len = _dbus_string_get_length (&block->
replacement);
1176 realign_reader = *realign_root;
1178#if RECURSIVE_MARSHAL_WRITE_TRACE
1179 _dbus_verbose (
"INITIALIZING replacement block writer %p at value_pos %d\n",
1180 &writer, _dbus_string_get_length (&block->
replacement));
1191#if RECURSIVE_MARSHAL_WRITE_TRACE
1192 _dbus_verbose (
"COPYING from reader at value_pos %d to writer %p starting after value_pos %d\n",
1196 if (!_dbus_type_writer_write_reader_partial (&writer,
1204#if RECURSIVE_MARSHAL_WRITE_TRACE
1205 _dbus_verbose (
"REPLACEMENT at padding %d len %d\n", block->
padding,
1209 _dbus_verbose (
"TO BE REPLACED at value_pos = %d (align pad %d) len %d realign_reader.value_pos %d\n",
1229 apply_and_free_fixups (&fixups, reader);
1235 free_fixups (&fixups);
1282 if (!replacement_block_init (&block, reader))
1286#if RECURSIVE_MARSHAL_WRITE_TRACE
1287 _dbus_verbose (
"INITIALIZING writer %p to write basic value at value_pos %d of replacement string\n",
1288 &writer, _dbus_string_get_length (&block.
replacement));
1296#if RECURSIVE_MARSHAL_WRITE_TRACE
1297 _dbus_verbose (
"WRITING basic value to writer %p (replacement string)\n", &writer);
1302 if (!replacement_block_replace (&block,
1310 replacement_block_free (&block);
1374#if RECURSIVE_MARSHAL_WRITE_TRACE
1375 _dbus_verbose (
" SET BASIC type reader %p type_pos = %d value_pos = %d remaining sig '%s' realign_root = %p with value_pos %d current_type = %s\n",
1379 realign_root ? realign_root->
value_pos : -1,
1382 _dbus_string_get_length (realign_root->
value_str) -
1390 reader_set_basic_fixed_length (reader, current_type, value);
1396 return reader_set_basic_variable_length (reader, current_type,
1397 value, realign_root);
1430 if (!replacement_block_init (&block, reader))
1433 if (!replacement_block_replace (&block,
1441 replacement_block_free (&block);
1508#if RECURSIVE_MARSHAL_WRITE_TRACE
1509 _dbus_verbose (
"writer %p init remaining sig '%s'\n", writer,
1533 NULL, 0, value_str, value_pos);
1592 value_str, value_pos);
1598_dbus_type_writer_write_basic_no_typecode (
DBusTypeWriter *writer,
1656#ifndef DBUS_DISABLE_CHECKS
1667 "The overall signature expected here was '%s' and we are on byte %d of that signature.",
1673 "The overall signature expected here was '%s' and we are on byte %d of that signature.",
1682#if RECURSIVE_MARSHAL_WRITE_TRACE
1683 _dbus_verbose (
" type writer %p recurse parent %s type_pos = %d value_pos = %d is_expectation = %d remaining sig '%s' enabled = %d\n",
1691 _dbus_verbose (
" type writer %p recurse sub %s type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
1709#if RECURSIVE_MARSHAL_WRITE_TRACE
1710 _dbus_verbose (
" type writer %p write_or_verify start type_pos = %d remaining sig '%s' enabled = %d\n",
1723#ifndef DBUS_DISABLE_CHECKS
1729 if (expected != typecode)
1733 "The overall signature expected here was '%s' and we are on byte %d of that signature.",
1737 _dbus_warn_check_failed (
"Array or variant type wasn't expecting any more values to be written into it, but a value %s was written.\n"
1738 "The overall signature expected here was '%s' and we are on byte %d of that signature.",
1763#if RECURSIVE_MARSHAL_WRITE_TRACE
1764 _dbus_verbose (
" type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
1776 int contained_type_start,
1777 int contained_type_len,
1792 if (!write_or_verify_typecode (sub, begin_char))
1812 int contained_type_start,
1813 int contained_type_len,
1821#ifndef DBUS_DISABLE_CHECKS
1826 contained_type_start,
1831 _dbus_warn_check_failed (
"Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array",
1832 _dbus_string_get_const_data_len (contained_type,
1833 contained_type_start,
1834 contained_type_len));
1840 if (writer->
enabled && !is_array_append)
1871 contained_type_start, contained_type_len,
1883 writer->
type_pos += 1 + contained_type_len;
1893 if (is_array_append)
1910 alignment = element_type_get_alignment (contained_type, contained_type_start);
1912 aligned = _DBUS_ALIGN_VALUE (sub->
value_pos, alignment);
1915 if (!is_array_append)
1929 if (is_array_append)
1936 _dbus_string_get_const_udata_len (sub->
value_str,
1953#if RECURSIVE_MARSHAL_WRITE_TRACE
1954 _dbus_verbose (
" type writer %p recurse array done remaining sig '%s' array start_pos = %d len_pos = %d value_pos = %d\n", sub,
1985 int contained_type_start,
1986 int contained_type_len,
1989 int contained_alignment;
2019 contained_type_len))
2057 int contained_type_start,
2058 int contained_type_len,
2062 writer_recurse_init_and_check (writer, container_type, sub);
2064 switch (container_type)
2067 return writer_recurse_struct_or_dict_entry (writer,
2070 contained_type_start, contained_type_len,
2074 return writer_recurse_struct_or_dict_entry (writer,
2077 contained_type_start, contained_type_len,
2081 return writer_recurse_array (writer,
2082 contained_type, contained_type_start, contained_type_len,
2083 sub, is_array_append);
2086 return writer_recurse_variant (writer,
2087 contained_type, contained_type_start, contained_type_len,
2111 int contained_type_start,
2114 int contained_type_len;
2117 contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
2119 contained_type_len = 0;
2121 return _dbus_type_writer_recurse_contained_len (writer, container_type,
2123 contained_type_start,
2144 int contained_type_start,
2147 int contained_type_len;
2150 contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
2152 contained_type_len = 0;
2154 return _dbus_type_writer_recurse_contained_len (writer,
DBUS_TYPE_ARRAY,
2156 contained_type_start,
2185#if RECURSIVE_MARSHAL_WRITE_TRACE
2186 _dbus_verbose (
" type writer %p unrecurse type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
2189 _dbus_verbose (
" type writer %p unrecurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
2212 len = writer_get_array_len (sub);
2217#if RECURSIVE_MARSHAL_WRITE_TRACE
2218 _dbus_verbose (
" filled in sub array len to %u at len_pos %d\n",
2222#if RECURSIVE_MARSHAL_WRITE_TRACE
2225 _dbus_verbose (
" not filling in sub array len because we were disabled when we passed the len\n");
2290#if RECURSIVE_MARSHAL_WRITE_TRACE
2291 _dbus_verbose (
" type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
2325 if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
2328 if (!write_or_verify_typecode (writer, type))
2334#if RECURSIVE_MARSHAL_WRITE_TRACE
2335 _dbus_verbose (
" type writer %p basic type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
2368#if RECURSIVE_MARSHAL_WRITE_TRACE
2369 _dbus_verbose (
" type writer %p entering fixed multi type_pos = %d value_pos = %d n_elements %d\n",
2373 if (!write_or_verify_typecode (writer, element_type))
2388#if RECURSIVE_MARSHAL_WRITE_TRACE
2389 _dbus_verbose (
" type writer %p fixed multi written new type_pos = %d new value_pos = %d n_elements %d\n",
2403 if (!writer->
enabled && _dbus_type_reader_greater_than (reader, start_after))
2405 _dbus_type_writer_set_enabled (writer,
TRUE);
2406#if RECURSIVE_MARSHAL_WRITE_TRACE
2407 _dbus_verbose (
"ENABLING writer %p at %d because reader at value_pos %d is after reader at value_pos %d\n",
2412 _dbus_assert ((!writer->
enabled && !_dbus_type_reader_greater_than (reader, start_after)) ||
2413 (writer->
enabled && _dbus_type_reader_greater_than (reader, start_after)));
2448 int start_after_new_pos,
2449 int start_after_new_len,
2466 int reader_array_len_pos;
2467 int reader_array_start_pos;
2475 if (!inside_start_after && start_after &&
2479 this_is_start_after =
TRUE;
2481 this_is_start_after =
FALSE;
2488 reader_array_start_pos = subreader.
u.array.
start_pos;
2493 reader_array_len_pos = -1;
2494 reader_array_start_pos = -1;
2498 &sig_start, &sig_len);
2500#if RECURSIVE_MARSHAL_WRITE_TRACE
2501 _dbus_verbose (
"about to recurse into %s reader at %d subreader at %d writer at %d start_after reader at %d write target len %d inside_start_after = %d this_is_start_after = %d\n",
2506 start_after ? start_after->
value_pos : -1,
2507 _dbus_string_get_length (writer->
value_str),
2508 inside_start_after, this_is_start_after);
2511 if (!inside_start_after && !this_is_start_after)
2512 enable_if_after (writer, &subreader, start_after);
2513 enabled_at_recurse = writer->
enabled;
2514 if (!_dbus_type_writer_recurse_contained_len (writer, current_type,
2515 sig_str, sig_start, sig_len,
2519#if RECURSIVE_MARSHAL_WRITE_TRACE
2520 _dbus_verbose (
"recursed into subwriter at %d write target len %d\n",
2522 _dbus_string_get_length (subwriter.
value_str));
2525 if (!writer_write_reader_helper (&subwriter, &subreader, start_after,
2526 start_after_new_pos, start_after_new_len,
2528 inside_start_after ||
2529 this_is_start_after))
2532#if RECURSIVE_MARSHAL_WRITE_TRACE
2533 _dbus_verbose (
"about to unrecurse from %s subreader at %d writer at %d subwriter at %d write target len %d\n",
2538 _dbus_string_get_length (writer->
value_str));
2541 if (!inside_start_after && !this_is_start_after)
2542 enable_if_after (writer, &subreader, start_after);
2543 past_start_after = writer->
enabled;
2552 if (start_after !=
NULL &&
2553 !enabled_at_recurse && past_start_after &&