From c7816d45e82ba8dd7e1e969c2cb6c3a27577cf68 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Fri, 28 Jan 2005 05:30:53 +0000 Subject: 2005-01-28 Havoc Pennington * doc/dbus-specification.xml: update to describe 16-bit types and dict entries * dbus/dbus-marshal-basic.c (_dbus_unpack_uint16): fix broken assertion * dbus/dbus-protocol.h (DBUS_TYPE_DICT_ENTRY): add DICT_ENTRY as a type * dbus/dbus-marshal-recursive.c: implement --- dbus/dbus-marshal-recursive.c | 152 +++++++++++++++++++++++++++++++++++------- 1 file changed, 127 insertions(+), 25 deletions(-) (limited to 'dbus/dbus-marshal-recursive.c') diff --git a/dbus/dbus-marshal-recursive.c b/dbus/dbus-marshal-recursive.c index 09bf1742..738edd91 100644 --- a/dbus/dbus-marshal-recursive.c +++ b/dbus/dbus-marshal-recursive.c @@ -159,24 +159,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); } @@ -321,11 +323,13 @@ skip_one_complete_type (const DBusString *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) { @@ -354,6 +358,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; @@ -381,6 +412,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 */ @@ -460,6 +492,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) @@ -495,6 +548,7 @@ array_reader_next (DBusTypeReader *reader, 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: { @@ -582,7 +636,7 @@ static const DBusTypeReaderClass body_types_only_reader_class = { static const DBusTypeReaderClass struct_reader_class = { "struct", 2, FALSE, - struct_reader_recurse, + struct_or_dict_entry_reader_recurse, NULL, struct_reader_next, NULL @@ -591,14 +645,32 @@ static const DBusTypeReaderClass struct_reader_class = { 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, NULL }; +static const DBusTypeReaderClass dict_entry_reader_class = { + "dict_entry", 4, + FALSE, + struct_or_dict_entry_reader_recurse, + NULL, + dict_entry_reader_next, + NULL +}; + +static const DBusTypeReaderClass dict_entry_types_only_reader_class = { + "dict_entry types", 5, + TRUE, + struct_or_dict_entry_types_only_reader_recurse, + NULL, + dict_entry_reader_next, + NULL +}; + static const DBusTypeReaderClass array_reader_class = { - "array", 4, + "array", 6, FALSE, array_reader_recurse, array_reader_check_finished, @@ -607,7 +679,7 @@ static const DBusTypeReaderClass array_reader_class = { }; static const DBusTypeReaderClass array_types_only_reader_class = { - "array types", 5, + "array types", 7, TRUE, array_types_only_reader_recurse, NULL, @@ -616,7 +688,7 @@ static const DBusTypeReaderClass array_types_only_reader_class = { }; static const DBusTypeReaderClass variant_reader_class = { - "variant", 6, + "variant", 8, FALSE, variant_reader_recurse, NULL, @@ -630,6 +702,8 @@ all_reader_classes[] = { &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 @@ -798,11 +872,13 @@ _dbus_type_reader_get_current_type (const DBusTypeReader *reader) t = DBUS_TYPE_INVALID; else t = _dbus_first_type_in_signature (reader->type_str, - reader->type_pos); + 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, @@ -989,6 +1065,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; @@ -1734,11 +1816,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 @@ -1752,7 +1835,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) @@ -2027,9 +2110,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, @@ -2151,6 +2243,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 */ @@ -2217,11 +2314,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 */ -- cgit