X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dbus%2Fdbus-marshal-recursive.c;h=4adfd2e9f3d03355045cb0a89aac12fba419185b;hb=67f9cca382df0d03adfe6b619aa613d103fa77f6;hp=e25fe2490b249e29bfc1228cf5997300be85356d;hpb=7bf62e31a3c820852271768fafc04ba95c31a19f;p=platform%2Fupstream%2Fdbus.git diff --git a/dbus/dbus-marshal-recursive.c b/dbus/dbus-marshal-recursive.c index e25fe24..4adfd2e 100644 --- a/dbus/dbus-marshal-recursive.c +++ b/dbus/dbus-marshal-recursive.c @@ -1,4 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* dbus-marshal-recursive.c Marshalling routines for recursive types * * Copyright (C) 2004, 2005 Red Hat, Inc. @@ -17,12 +17,14 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ +#include #include "dbus-marshal-recursive.h" #include "dbus-marshal-basic.h" +#include "dbus-signature.h" #include "dbus-internals.h" /** @@ -30,6 +32,18 @@ * @{ */ +static dbus_bool_t _dbus_type_reader_greater_than (const DBusTypeReader *lhs, + const DBusTypeReader *rhs); + +static void _dbus_type_writer_set_enabled (DBusTypeWriter *writer, + dbus_bool_t enabled); +static dbus_bool_t _dbus_type_writer_write_reader_partial (DBusTypeWriter *writer, + DBusTypeReader *reader, + const DBusTypeReader *start_after, + int start_after_new_pos, + int start_after_new_len, + DBusList **fixups); + /** turn this on to get deluged in TypeReader verbose spam */ #define RECURSIVE_MARSHAL_READ_TRACE 0 @@ -118,29 +132,13 @@ struct DBusTypeReaderClass dbus_bool_t (* check_finished) (const DBusTypeReader *reader); /**< check whether reader is at the end */ void (* next) (DBusTypeReader *reader, int current_type); /**< go to the next value */ - void (* init_from_mark) (DBusTypeReader *reader, - const DBusTypeMark *mark); /**< uncompress from a mark */ }; static int -first_type_in_signature (const DBusString *str, - int pos) -{ - unsigned char t; - - t = _dbus_string_get_byte (str, pos); - - if (t == DBUS_STRUCT_BEGIN_CHAR) - return DBUS_TYPE_STRUCT; - else - return t; -} - -static int element_type_get_alignment (const DBusString *str, int pos) { - return _dbus_type_get_alignment (first_type_in_signature (str, pos)); + return _dbus_type_get_alignment (_dbus_first_type_in_signature (str, pos)); } static void @@ -173,24 +171,26 @@ base_reader_recurse (DBusTypeReader *sub, } static void -struct_types_only_reader_recurse (DBusTypeReader *sub, - DBusTypeReader *parent) +struct_or_dict_entry_types_only_reader_recurse (DBusTypeReader *sub, + DBusTypeReader *parent) { base_reader_recurse (sub, parent); - + _dbus_assert (_dbus_string_get_byte (sub->type_str, - sub->type_pos) == DBUS_STRUCT_BEGIN_CHAR); + sub->type_pos) == DBUS_STRUCT_BEGIN_CHAR || + _dbus_string_get_byte (sub->type_str, + sub->type_pos) == DBUS_DICT_ENTRY_BEGIN_CHAR); sub->type_pos += 1; } static void -struct_reader_recurse (DBusTypeReader *sub, - DBusTypeReader *parent) +struct_or_dict_entry_reader_recurse (DBusTypeReader *sub, + DBusTypeReader *parent) { - struct_types_only_reader_recurse (sub, parent); + struct_or_dict_entry_types_only_reader_recurse (sub, parent); - /* struct has 8 byte alignment */ + /* struct and dict entry have 8 byte alignment */ sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8); } @@ -265,7 +265,7 @@ array_reader_recurse (DBusTypeReader *sub, sub->u.array.start_pos, sub->array_len_offset, array_reader_get_array_len (sub), - _dbus_type_to_string (first_type_in_signature (sub->type_str, + _dbus_type_to_string (_dbus_first_type_in_signature (sub->type_str, sub->type_pos))); #endif } @@ -275,6 +275,7 @@ variant_reader_recurse (DBusTypeReader *sub, DBusTypeReader *parent) { int sig_len; + int contained_alignment; base_reader_recurse (sub, parent); @@ -289,7 +290,10 @@ variant_reader_recurse (DBusTypeReader *sub, sub->value_pos = sub->type_pos + sig_len + 1; - sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8); + contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (sub->type_str, + sub->type_pos)); + + sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment); #if RECURSIVE_MARSHAL_READ_TRACE _dbus_verbose (" type reader %p variant containing '%s'\n", @@ -316,26 +320,43 @@ array_reader_check_finished (const DBusTypeReader *reader) return reader->value_pos == end_pos; } -/* this is written a little oddly to try and overoptimize */ static void skip_one_complete_type (const DBusString *type_str, int *type_pos) { + _dbus_type_signature_next (_dbus_string_get_const_data (type_str), + type_pos); +} + +/** + * Skips to the next "complete" type inside a type signature. + * The signature is read starting at type_pos, and the next + * type position is stored in the same variable. + * + * @param type_str a type signature (must be valid) + * @param type_pos an integer position in the type signature (in and out) + */ +void +_dbus_type_signature_next (const char *type_str, + int *type_pos) +{ const unsigned char *p; const unsigned char *start; _dbus_assert (type_str != NULL); _dbus_assert (type_pos != NULL); - start = _dbus_string_get_const_data (type_str); + start = type_str; p = start + *type_pos; _dbus_assert (*p != DBUS_STRUCT_END_CHAR); + _dbus_assert (*p != DBUS_DICT_ENTRY_END_CHAR); while (*p == DBUS_TYPE_ARRAY) ++p; _dbus_assert (*p != DBUS_STRUCT_END_CHAR); + _dbus_assert (*p != DBUS_DICT_ENTRY_END_CHAR); if (*p == DBUS_STRUCT_BEGIN_CHAR) { @@ -364,6 +385,33 @@ skip_one_complete_type (const DBusString *type_str, } } } + else if (*p == DBUS_DICT_ENTRY_BEGIN_CHAR) + { + int depth; + + depth = 1; + + while (TRUE) + { + _dbus_assert (*p != DBUS_TYPE_INVALID); + + ++p; + + _dbus_assert (*p != DBUS_TYPE_INVALID); + + if (*p == DBUS_DICT_ENTRY_BEGIN_CHAR) + depth += 1; + else if (*p == DBUS_DICT_ENTRY_END_CHAR) + { + depth -= 1; + if (depth == 0) + { + ++p; + break; + } + } + } + } else { ++p; @@ -391,6 +439,7 @@ base_reader_next (DBusTypeReader *reader, { switch (current_type) { + case DBUS_TYPE_DICT_ENTRY: case DBUS_TYPE_STRUCT: case DBUS_TYPE_VARIANT: /* Scan forward over the entire container contents */ @@ -429,8 +478,8 @@ base_reader_next (DBusTypeReader *reader, { if (!reader->klass->types_only) _dbus_marshal_skip_array (reader->value_str, - first_type_in_signature (reader->type_str, - reader->type_pos + 1), + _dbus_first_type_in_signature (reader->type_str, + reader->type_pos + 1), reader->byte_order, &reader->value_pos); @@ -471,6 +520,27 @@ struct_reader_next (DBusTypeReader *reader, } static void +dict_entry_reader_next (DBusTypeReader *reader, + int current_type) +{ + int t; + + base_reader_next (reader, current_type); + + /* for STRUCT containers we return FALSE at the end of the struct, + * for INVALID we return FALSE at the end of the signature. + * In both cases we arrange for get_current_type() to return INVALID + * which is defined to happen iff we're at the end (no more next()) + */ + t = _dbus_string_get_byte (reader->type_str, reader->type_pos); + if (t == DBUS_DICT_ENTRY_END_CHAR) + { + reader->type_pos += 1; + reader->finished = TRUE; + } +} + +static void array_types_only_reader_next (DBusTypeReader *reader, int current_type) { @@ -502,9 +572,10 @@ array_reader_next (DBusTypeReader *reader, _dbus_assert (reader->value_pos < end_pos); _dbus_assert (reader->value_pos >= reader->u.array.start_pos); - switch (first_type_in_signature (reader->type_str, - reader->type_pos)) + switch (_dbus_first_type_in_signature (reader->type_str, + reader->type_pos)) { + case DBUS_TYPE_DICT_ENTRY: case DBUS_TYPE_STRUCT: case DBUS_TYPE_VARIANT: { @@ -527,7 +598,7 @@ array_reader_next (DBusTypeReader *reader, case DBUS_TYPE_ARRAY: { _dbus_marshal_skip_array (reader->value_str, - first_type_in_signature (reader->type_str, + _dbus_first_type_in_signature (reader->type_str, reader->type_pos + 1), reader->byte_order, &reader->value_pos); @@ -560,24 +631,12 @@ array_reader_next (DBusTypeReader *reader, } } -static void -array_init_from_mark (DBusTypeReader *reader, - const DBusTypeMark *mark) -{ - /* Fill in the array-specific fields from the mark. The general - * fields are already filled in. - */ - reader->u.array.start_pos = mark->array_start_pos; - reader->array_len_offset = mark->array_len_offset; -} - static const DBusTypeReaderClass body_reader_class = { "body", 0, FALSE, NULL, /* body is always toplevel, so doesn't get recursed into */ NULL, - base_reader_next, - NULL + base_reader_next }; static const DBusTypeReaderClass body_types_only_reader_class = { @@ -585,65 +644,79 @@ static const DBusTypeReaderClass body_types_only_reader_class = { TRUE, NULL, /* body is always toplevel, so doesn't get recursed into */ NULL, - base_reader_next, - NULL + base_reader_next }; static const DBusTypeReaderClass struct_reader_class = { "struct", 2, FALSE, - struct_reader_recurse, + struct_or_dict_entry_reader_recurse, NULL, - struct_reader_next, - NULL + struct_reader_next }; static const DBusTypeReaderClass struct_types_only_reader_class = { "struct types", 3, TRUE, - struct_types_only_reader_recurse, + struct_or_dict_entry_types_only_reader_recurse, + NULL, + struct_reader_next +}; + +static const DBusTypeReaderClass dict_entry_reader_class = { + "dict_entry", 4, + FALSE, + struct_or_dict_entry_reader_recurse, + NULL, + dict_entry_reader_next +}; + +static const DBusTypeReaderClass dict_entry_types_only_reader_class = { + "dict_entry types", 5, + TRUE, + struct_or_dict_entry_types_only_reader_recurse, NULL, - struct_reader_next, - NULL + dict_entry_reader_next }; static const DBusTypeReaderClass array_reader_class = { - "array", 4, + "array", 6, FALSE, array_reader_recurse, array_reader_check_finished, - array_reader_next, - array_init_from_mark + array_reader_next }; static const DBusTypeReaderClass array_types_only_reader_class = { - "array types", 5, + "array types", 7, TRUE, array_types_only_reader_recurse, NULL, - array_types_only_reader_next, - NULL + array_types_only_reader_next }; static const DBusTypeReaderClass variant_reader_class = { - "variant", 6, + "variant", 8, FALSE, variant_reader_recurse, NULL, - base_reader_next, - NULL + base_reader_next }; -static const DBusTypeReaderClass const * +#ifndef DBUS_DISABLE_ASSERT +static const DBusTypeReaderClass * const all_reader_classes[] = { &body_reader_class, &body_types_only_reader_class, &struct_reader_class, &struct_types_only_reader_class, + &dict_entry_reader_class, + &dict_entry_types_only_reader_class, &array_reader_class, &array_types_only_reader_class, &variant_reader_class }; +#endif /** * Initializes a type reader. @@ -676,41 +749,6 @@ _dbus_type_reader_init (DBusTypeReader *reader, } /** - * Initializes a type reader that's been compressed into a - * DBusTypeMark. The args have to be the same as those passed in to - * create the original #DBusTypeReader. - * - * @param reader the reader - * @param byte_order the byte order of the value block - * @param type_str string containing the type signature - * @param value_str string containing the values block - * @param mark the mark to decompress from - */ -void -_dbus_type_reader_init_from_mark (DBusTypeReader *reader, - int byte_order, - const DBusString *type_str, - const DBusString *value_str, - const DBusTypeMark *mark) -{ - reader->klass = all_reader_classes[mark->container_type]; - - reader_init (reader, byte_order, - mark->type_pos_in_value_str ? value_str : type_str, - mark->type_pos, - value_str, mark->value_pos); - - if (reader->klass->init_from_mark) - (* reader->klass->init_from_mark) (reader, mark); - -#if RECURSIVE_MARSHAL_READ_TRACE - _dbus_verbose (" type reader %p init from mark type_pos = %d value_pos = %d remaining sig '%s'\n", - reader, reader->type_pos, reader->value_pos, - _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0)); -#endif -} - -/** * Like _dbus_type_reader_init() but the iteration is over the * signature, not over values. * @@ -736,60 +774,6 @@ _dbus_type_reader_init_types_only (DBusTypeReader *reader, } /** - * Like _dbus_type_reader_init_from_mark() but only iterates over - * the signature, not the values. - * - * @param reader the reader - * @param type_str the signature string - * @param mark the mark to decompress from - */ -void -_dbus_type_reader_init_types_only_from_mark (DBusTypeReader *reader, - const DBusString *type_str, - const DBusTypeMark *mark) -{ - reader->klass = all_reader_classes[mark->container_type]; - _dbus_assert (reader->klass->types_only); - _dbus_assert (!mark->type_pos_in_value_str); - - reader_init (reader, DBUS_COMPILER_BYTE_ORDER, /* irrelevant */ - type_str, mark->type_pos, - NULL, _DBUS_INT_MAX /* crashes if we screw up */); - - if (reader->klass->init_from_mark) - (* reader->klass->init_from_mark) (reader, mark); - -#if RECURSIVE_MARSHAL_READ_TRACE - _dbus_verbose (" type reader %p init types only from mark type_pos = %d remaining sig '%s'\n", - reader, reader->type_pos, - _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0)); -#endif -} - -/** - * Compresses a type reader into a #DBusTypeMark, useful for example - * if you want to cache a bunch of positions in a block of values. - * - * @param reader the reader - * @param mark the mark to init - */ -void -_dbus_type_reader_save_mark (const DBusTypeReader *reader, - DBusTypeMark *mark) -{ - mark->type_pos_in_value_str = (reader->type_str == reader->value_str); - mark->container_type = reader->klass->id; - _dbus_assert (all_reader_classes[reader->klass->id] == reader->klass); - - mark->type_pos = reader->type_pos; - mark->value_pos = reader->value_pos; - - /* these are just junk if the reader isn't really an array of course */ - mark->array_len_offset = reader->array_len_offset; - mark->array_start_pos = reader->u.array.start_pos; -} - -/** * Gets the type of the value the reader is currently pointing to; * or for a types-only reader gets the type it's currently pointing to. * If the reader is at the end of a block or end of a container such @@ -807,12 +791,14 @@ _dbus_type_reader_get_current_type (const DBusTypeReader *reader) (* reader->klass->check_finished) (reader))) t = DBUS_TYPE_INVALID; else - t = first_type_in_signature (reader->type_str, - reader->type_pos); + t = _dbus_first_type_in_signature (reader->type_str, + reader->type_pos); _dbus_assert (t != DBUS_STRUCT_END_CHAR); _dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR); - + _dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR); + _dbus_assert (t != DBUS_DICT_ENTRY_BEGIN_CHAR); + #if 0 _dbus_verbose (" type reader %p current type_pos = %d type = %s\n", reader, reader->type_pos, @@ -837,7 +823,7 @@ _dbus_type_reader_get_element_type (const DBusTypeReader *reader) _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY); - element_type = first_type_in_signature (reader->type_str, + element_type = _dbus_first_type_in_signature (reader->type_str, reader->type_pos + 1); return element_type; @@ -904,6 +890,21 @@ _dbus_type_reader_read_basic (const DBusTypeReader *reader, } /** + * Returns the number of bytes in the array. + * + * @param reader the reader to read from + * @returns the number of bytes in the array + */ +int +_dbus_type_reader_get_array_length (const DBusTypeReader *reader) +{ + _dbus_assert (!reader->klass->types_only); + _dbus_assert (reader->klass == &array_reader_class); + + return array_reader_get_array_len (reader); +} + +/** * Reads a block of fixed-length basic values, from the current point * in an array to the end of the array. Does not work for arrays of * string or container types. @@ -932,11 +933,11 @@ _dbus_type_reader_read_fixed_multi (const DBusTypeReader *reader, _dbus_assert (!reader->klass->types_only); _dbus_assert (reader->klass == &array_reader_class); - element_type = first_type_in_signature (reader->type_str, - reader->type_pos); + element_type = _dbus_first_type_in_signature (reader->type_str, + reader->type_pos); _dbus_assert (element_type != DBUS_TYPE_INVALID); /* why we don't use get_current_type() */ - _dbus_assert (_dbus_type_is_fixed (element_type)); + _dbus_assert (dbus_type_is_fixed (element_type)); alignment = _dbus_type_get_alignment (element_type); @@ -989,7 +990,7 @@ _dbus_type_reader_recurse (DBusTypeReader *reader, { int t; - t = first_type_in_signature (reader->type_str, reader->type_pos); + t = _dbus_first_type_in_signature (reader->type_str, reader->type_pos); switch (t) { @@ -999,6 +1000,12 @@ _dbus_type_reader_recurse (DBusTypeReader *reader, else sub->klass = &struct_reader_class; break; + case DBUS_TYPE_DICT_ENTRY: + if (reader->klass->types_only) + sub->klass = &dict_entry_types_only_reader_class; + else + sub->klass = &dict_entry_reader_class; + break; case DBUS_TYPE_ARRAY: if (reader->klass->types_only) sub->klass = &array_types_only_reader_class; @@ -1015,7 +1022,7 @@ _dbus_type_reader_recurse (DBusTypeReader *reader, _dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t)); #ifndef DBUS_DISABLE_CHECKS if (t == DBUS_TYPE_INVALID) - _dbus_warn ("You can't recurse into an empty array or off the end of a message body\n"); + _dbus_warn_check_failed ("You can't recurse into an empty array or off the end of a message body\n"); #endif /* DBUS_DISABLE_CHECKS */ _dbus_assert_not_reached ("don't yet handle recursing into this type"); @@ -1124,8 +1131,8 @@ _dbus_type_reader_get_signature (const DBusTypeReader *reader, typedef struct { - DBusString replacement; - int padding; + DBusString replacement; /**< Marshaled value including alignment padding */ + int padding; /**< How much of the replacement block is padding */ } ReplacementBlock; static dbus_bool_t @@ -1338,7 +1345,7 @@ reader_set_basic_fixed_length (DBusTypeReader *reader, * type and value strings and set_basic would be a method on that * object... this would also make DBusTypeReader the same thing as * DBusTypeMark. But since DBusMessage is effectively that object for - * D-BUS it doesn't seem worth creating some random object.) + * D-Bus it doesn't seem worth creating some random object.) * * @todo optimize this by only rewriting until the old and new values * are at the same alignment. Frequently this should result in only @@ -1374,9 +1381,9 @@ _dbus_type_reader_set_basic (DBusTypeReader *reader, realign_root->value_pos); #endif - _dbus_assert (_dbus_type_is_basic (current_type)); + _dbus_assert (dbus_type_is_basic (current_type)); - if (_dbus_type_is_fixed (current_type)) + if (dbus_type_is_fixed (current_type)) { reader_set_basic_fixed_length (reader, current_type, value); return TRUE; @@ -1433,7 +1440,7 @@ _dbus_type_reader_delete (DBusTypeReader *reader, return retval; } -/** +/* * Compares two readers, which must be iterating over the same value data. * Returns #TRUE if the first parameter is further along than the second parameter. * @@ -1441,7 +1448,7 @@ _dbus_type_reader_delete (DBusTypeReader *reader, * @param rhs left-hand-side (first) parameter * @returns whether lhs is greater than rhs */ -dbus_bool_t +static dbus_bool_t _dbus_type_reader_greater_than (const DBusTypeReader *lhs, const DBusTypeReader *rhs) { @@ -1461,7 +1468,7 @@ _dbus_type_reader_greater_than (const DBusTypeReader *lhs, /** * Initialize a write iterator, which is used to write out values in - * serialized D-BUS format. + * serialized D-Bus format. * * The type_pos passed in is expected to be inside an already-valid, * though potentially empty, type signature. This means that the byte @@ -1649,13 +1656,22 @@ writer_recurse_init_and_check (DBusTypeWriter *writer, { int expected; - expected = first_type_in_signature (writer->type_str, writer->type_pos); + expected = _dbus_first_type_in_signature (writer->type_str, writer->type_pos); if (expected != sub->container_type) { - _dbus_warn ("Writing an element of type %s, but the expected type here is %s\n", - _dbus_type_to_string (sub->container_type), - _dbus_type_to_string (expected)); + if (expected != DBUS_TYPE_INVALID) + _dbus_warn_check_failed ("Writing an element of type %s, but the expected type here is %s\n" + "The overall signature expected here was '%s' and we are on byte %d of that signature.\n", + _dbus_type_to_string (sub->container_type), + _dbus_type_to_string (expected), + _dbus_string_get_const_data (writer->type_str), writer->type_pos); + else + _dbus_warn_check_failed ("Writing an element of type %s, but no value is expected here\n" + "The overall signature expected here was '%s' and we are on byte %d of that signature.\n", + _dbus_type_to_string (sub->container_type), + _dbus_string_get_const_data (writer->type_str), writer->type_pos); + _dbus_assert_not_reached ("bad array element or variant content written"); } } @@ -1710,8 +1726,16 @@ write_or_verify_typecode (DBusTypeWriter *writer, if (expected != typecode) { - _dbus_warn ("Array or variant type requires that type %s be written, but %s was written\n", - _dbus_type_to_string (expected), _dbus_type_to_string (typecode)); + if (expected != DBUS_TYPE_INVALID) + _dbus_warn_check_failed ("Array or variant type requires that type %s be written, but %s was written.\n" + "The overall signature expected here was '%s' and we are on byte %d of that signature.\n", + _dbus_type_to_string (expected), _dbus_type_to_string (typecode), + _dbus_string_get_const_data (writer->type_str), writer->type_pos); + else + _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" + "The overall signature expected here was '%s' and we are on byte %d of that signature.\n", + _dbus_type_to_string (typecode), + _dbus_string_get_const_data (writer->type_str), writer->type_pos); _dbus_assert_not_reached ("bad type inserted somewhere inside an array or variant"); } } @@ -1744,11 +1768,12 @@ write_or_verify_typecode (DBusTypeWriter *writer, } static dbus_bool_t -writer_recurse_struct (DBusTypeWriter *writer, - const DBusString *contained_type, - int contained_type_start, - int contained_type_len, - DBusTypeWriter *sub) +writer_recurse_struct_or_dict_entry (DBusTypeWriter *writer, + int begin_char, + const DBusString *contained_type, + int contained_type_start, + int contained_type_len, + DBusTypeWriter *sub) { /* FIXME right now contained_type is ignored; we could probably * almost trivially fix the code so if it's present we @@ -1762,7 +1787,7 @@ writer_recurse_struct (DBusTypeWriter *writer, return FALSE; } - if (!write_or_verify_typecode (sub, DBUS_STRUCT_BEGIN_CHAR)) + if (!write_or_verify_typecode (sub, begin_char)) _dbus_assert_not_reached ("failed to insert struct typecode after prealloc"); if (writer->enabled) @@ -1801,10 +1826,10 @@ writer_recurse_array (DBusTypeWriter *writer, writer->type_str, writer->u.array.element_type_pos + 1)) { - _dbus_warn ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n", - _dbus_string_get_const_data_len (contained_type, - contained_type_start, - contained_type_len)); + _dbus_warn_check_failed ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n", + _dbus_string_get_const_data_len (contained_type, + contained_type_start, + contained_type_len)); _dbus_assert_not_reached ("incompatible type for child array"); } } @@ -1937,7 +1962,7 @@ writer_recurse_array (DBusTypeWriter *writer, /* Variant value will normally have: * 1 byte signature length not including nul * signature typecodes (nul terminated) - * padding to 8-boundary + * padding to alignment of contained type * body according to signature * * The signature string can only have a single type @@ -1945,21 +1970,12 @@ writer_recurse_array (DBusTypeWriter *writer, * * So a typical variant type with the integer 3 will have these * octets: - * 0x1 'i' '\0' [padding to 8-boundary] 0x0 0x0 0x0 0x3 - * - * For an array of 4-byte types stuffed into variants, the padding to - * 8-boundary is only the 1 byte that is required for the 4-boundary - * anyhow for all array elements after the first one. And for single - * variants in isolation, wasting a few bytes is hardly a big deal. + * 0x1 'i' '\0' [1 byte padding to alignment boundary] 0x0 0x0 0x0 0x3 * * The main world of hurt for writing out a variant is that the type * string is the same string as the value string. Which means * inserting to the type string will move the value_pos; and it means * that inserting to the type string could break type alignment. - * - * This type alignment issue is why the body of the variant is always - * 8-aligned. Then we know that re-8-aligning the start of the body - * will always correctly align the full contents of the variant type. */ static dbus_bool_t writer_recurse_variant (DBusTypeWriter *writer, @@ -1968,6 +1984,8 @@ writer_recurse_variant (DBusTypeWriter *writer, int contained_type_len, DBusTypeWriter *sub) { + int contained_alignment; + if (writer->enabled) { /* Allocate space for the worst case, which is 1 byte sig @@ -2018,12 +2036,14 @@ writer_recurse_variant (DBusTypeWriter *writer, sub->value_pos += 1; + contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (contained_type, contained_type_start)); + if (!_dbus_string_insert_bytes (sub->value_str, sub->value_pos, - _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos, + _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment) - sub->value_pos, '\0')) _dbus_assert_not_reached ("should not have failed to insert alignment padding for variant body"); - sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8); + sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment); return TRUE; } @@ -2042,9 +2062,18 @@ _dbus_type_writer_recurse_contained_len (DBusTypeWriter *writer, switch (container_type) { case DBUS_TYPE_STRUCT: - return writer_recurse_struct (writer, - contained_type, contained_type_start, contained_type_len, - sub); + return writer_recurse_struct_or_dict_entry (writer, + DBUS_STRUCT_BEGIN_CHAR, + contained_type, + contained_type_start, contained_type_len, + sub); + break; + case DBUS_TYPE_DICT_ENTRY: + return writer_recurse_struct_or_dict_entry (writer, + DBUS_DICT_ENTRY_BEGIN_CHAR, + contained_type, + contained_type_start, contained_type_len, + sub); break; case DBUS_TYPE_ARRAY: return writer_recurse_array (writer, @@ -2166,6 +2195,11 @@ _dbus_type_writer_unrecurse (DBusTypeWriter *writer, if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR)) return FALSE; } + else if (sub->container_type == DBUS_TYPE_DICT_ENTRY) + { + if (!write_or_verify_typecode (sub, DBUS_DICT_ENTRY_END_CHAR)) + return FALSE; + } else if (sub->container_type == DBUS_TYPE_ARRAY) { if (sub->u.array.len_pos >= 0) /* len_pos == -1 if we weren't enabled when we passed it */ @@ -2232,11 +2266,16 @@ _dbus_type_writer_unrecurse (DBusTypeWriter *writer, * parent makes no difference since there's only one value * and we just finished writing it and won't use type_pos again * writer->type_pos should remain as-is + * + * + * For all these, DICT_ENTRY is the same as STRUCT */ if (writer->type_str != NULL) { - if (sub->container_type == DBUS_TYPE_STRUCT && + if ((sub->container_type == DBUS_TYPE_STRUCT || + sub->container_type == DBUS_TYPE_DICT_ENTRY) && (writer->container_type == DBUS_TYPE_STRUCT || + writer->container_type == DBUS_TYPE_DICT_ENTRY || writer->container_type == DBUS_TYPE_INVALID)) { /* Advance the parent to the next struct field */ @@ -2301,7 +2340,7 @@ _dbus_type_writer_write_basic (DBusTypeWriter *writer, /** * Writes a block of fixed-length basic values, i.e. those that are - * both _dbus_type_is_fixed() and _dbus_type_is_basic(). The block + * both dbus_type_is_fixed() and _dbus_type_is_basic(). The block * must be written inside an array. * * The value parameter should be the address of said array of values, @@ -2320,7 +2359,7 @@ _dbus_type_writer_write_fixed_multi (DBusTypeWriter *writer, int n_elements) { _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY); - _dbus_assert (_dbus_type_is_fixed (element_type)); + _dbus_assert (dbus_type_is_fixed (element_type)); _dbus_assert (writer->type_pos_is_expectation); _dbus_assert (n_elements >= 0); @@ -2413,7 +2452,7 @@ writer_write_reader_helper (DBusTypeWriter *writer, while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID) { - if (_dbus_type_is_container (current_type)) + if (dbus_type_is_container (current_type)) { DBusTypeReader subreader; DBusTypeWriter subwriter; @@ -2559,7 +2598,7 @@ writer_write_reader_helper (DBusTypeWriter *writer, { DBusBasicValue val; - _dbus_assert (_dbus_type_is_basic (current_type)); + _dbus_assert (dbus_type_is_basic (current_type)); #if RECURSIVE_MARSHAL_WRITE_TRACE _dbus_verbose ("Reading basic value %s at %d\n", @@ -2600,7 +2639,7 @@ writer_write_reader_helper (DBusTypeWriter *writer, return FALSE; } -/** +/* * Iterate through all values in the given reader, writing a copy of * each value to the writer. The reader will be moved forward to its * end position. @@ -2631,7 +2670,7 @@ writer_write_reader_helper (DBusTypeWriter *writer, * @param fixups list to append #DBusArrayLenFixup if the write was partial * @returns #FALSE if no memory */ -dbus_bool_t +static dbus_bool_t _dbus_type_writer_write_reader_partial (DBusTypeWriter *writer, DBusTypeReader *reader, const DBusTypeReader *start_after, @@ -2692,7 +2731,7 @@ _dbus_type_writer_write_reader (DBusTypeWriter *writer, return _dbus_type_writer_write_reader_partial (writer, reader, NULL, 0, 0, NULL); } -/** +/* * If disabled, a writer can still be iterated forward and recursed/unrecursed * but won't write any values. Types will still be written unless the * writer is a "values only" writer, because the writer needs access to @@ -2701,7 +2740,7 @@ _dbus_type_writer_write_reader (DBusTypeWriter *writer, * @param writer the type writer * @param enabled #TRUE if values should be written */ -void +static void _dbus_type_writer_set_enabled (DBusTypeWriter *writer, dbus_bool_t enabled) {