diff options
| -rw-r--r-- | ChangeLog | 13 | ||||
| -rw-r--r-- | dbus/dbus-marshal-basic.c | 20 | ||||
| -rw-r--r-- | dbus/dbus-marshal-byteswap.c | 1 | ||||
| -rw-r--r-- | dbus/dbus-marshal-recursive-util.c | 262 | ||||
| -rw-r--r-- | dbus/dbus-marshal-recursive.c | 152 | ||||
| -rw-r--r-- | dbus/dbus-marshal-validate.c | 33 | ||||
| -rw-r--r-- | dbus/dbus-marshal-validate.h | 9 | ||||
| -rw-r--r-- | dbus/dbus-message.c | 22 | ||||
| -rw-r--r-- | dbus/dbus-protocol.h | 13 | ||||
| -rw-r--r-- | doc/TODO | 9 | ||||
| -rw-r--r-- | doc/dbus-specification.xml | 54 | 
11 files changed, 543 insertions, 45 deletions
@@ -1,3 +1,16 @@ +2005-01-28  Havoc Pennington  <hp@redhat.com> + +	* 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 +  2005-01-27  Havoc Pennington  <hp@redhat.com>  	* dbus/dbus-arch-deps.h.in: add 16/32-bit types diff --git a/dbus/dbus-marshal-basic.c b/dbus/dbus-marshal-basic.c index e4f6720c..84a9ccaf 100644 --- a/dbus/dbus-marshal-basic.c +++ b/dbus/dbus-marshal-basic.c @@ -172,7 +172,7 @@ dbus_uint16_t  _dbus_unpack_uint16 (int                  byte_order,                       const unsigned char *data)  { -  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data); +  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);    if (byte_order == DBUS_LITTLE_ENDIAN)      return DBUS_UINT16_FROM_LE (*(dbus_uint16_t*)data); @@ -1245,8 +1245,10 @@ _dbus_type_get_alignment (int typecode)         * and it's simpler to just always align structs to 8;         * we want the amount of padding in a struct of a given         * type to be predictable, not location-dependent. +       * DICT_ENTRY is always the same as struct.         */      case DBUS_TYPE_STRUCT: +    case DBUS_TYPE_DICT_ENTRY:        return 8;      default: @@ -1283,6 +1285,7 @@ _dbus_type_is_valid (int typecode)      case DBUS_TYPE_SIGNATURE:      case DBUS_TYPE_ARRAY:      case DBUS_TYPE_STRUCT: +    case DBUS_TYPE_DICT_ENTRY:      case DBUS_TYPE_VARIANT:        return TRUE; @@ -1294,6 +1297,7 @@ _dbus_type_is_valid (int typecode)  /** macro that checks whether a typecode is a container type */  #define TYPE_IS_CONTAINER(typecode)             \      ((typecode) == DBUS_TYPE_STRUCT ||          \ +     (typecode) == DBUS_TYPE_DICT_ENTRY ||      \       (typecode) == DBUS_TYPE_VARIANT ||         \       (typecode) == DBUS_TYPE_ARRAY) @@ -1403,6 +1407,8 @@ _dbus_type_to_string (int typecode)        return "signature";      case DBUS_TYPE_STRUCT:        return "struct"; +    case DBUS_TYPE_DICT_ENTRY: +      return "dict_entry";      case DBUS_TYPE_ARRAY:        return "array";      case DBUS_TYPE_VARIANT: @@ -1411,6 +1417,10 @@ _dbus_type_to_string (int typecode)        return "begin_struct";      case DBUS_STRUCT_END_CHAR:        return "end_struct"; +    case DBUS_DICT_ENTRY_BEGIN_CHAR: +      return "begin_dict_entry"; +    case DBUS_DICT_ENTRY_END_CHAR: +      return "end_dict_entry";      default:        return "unknown";      } @@ -1559,8 +1569,14 @@ _dbus_first_type_in_signature (const DBusString *str,    if (t == DBUS_STRUCT_BEGIN_CHAR)      return DBUS_TYPE_STRUCT; +  else if (t == DBUS_DICT_ENTRY_BEGIN_CHAR) +    return DBUS_TYPE_DICT_ENTRY;    else -    return t; +    { +      _dbus_assert (t != DBUS_STRUCT_END_CHAR); +      _dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR); +      return t; +    }  }  /** @} */ diff --git a/dbus/dbus-marshal-byteswap.c b/dbus/dbus-marshal-byteswap.c index 7670ec45..c8ec8942 100644 --- a/dbus/dbus-marshal-byteswap.c +++ b/dbus/dbus-marshal-byteswap.c @@ -175,6 +175,7 @@ byteswap_body_helper (DBusTypeReader       *reader,            break;          case DBUS_TYPE_STRUCT: +        case DBUS_TYPE_DICT_ENTRY:            {              DBusTypeReader sub; diff --git a/dbus/dbus-marshal-recursive-util.c b/dbus/dbus-marshal-recursive-util.c index c607b046..6e8af18a 100644 --- a/dbus/dbus-marshal-recursive-util.c +++ b/dbus/dbus-marshal-recursive-util.c @@ -526,6 +526,19 @@ static dbus_bool_t struct_set_value        (TestTypeNode   *node,                                              int             seed);  static dbus_bool_t struct_build_signature  (TestTypeNode   *node,                                              DBusString     *str); +static dbus_bool_t dict_write_value        (TestTypeNode   *node, +                                            DataBlock      *block, +                                            DBusTypeWriter *writer, +                                            int             seed); +static dbus_bool_t dict_read_value         (TestTypeNode   *node, +                                            DBusTypeReader *reader, +                                            int             seed); +static dbus_bool_t dict_set_value          (TestTypeNode   *node, +                                            DBusTypeReader *reader, +                                            DBusTypeReader *realign_root, +                                            int             seed); +static dbus_bool_t dict_build_signature    (TestTypeNode   *node, +                                            DBusString     *str);  static dbus_bool_t array_write_value       (TestTypeNode   *node,                                              DataBlock      *block,                                              DBusTypeWriter *writer, @@ -553,6 +566,7 @@ static dbus_bool_t variant_set_value       (TestTypeNode   *node,  static void        container_destroy       (TestTypeNode   *node); +  static const TestTypeNodeClass int16_class = {    DBUS_TYPE_INT16,    sizeof (TestTypeNode), @@ -793,6 +807,20 @@ static const TestTypeNodeClass struct_2_class = {    NULL  }; +static const TestTypeNodeClass dict_1_class = { +  DBUS_TYPE_ARRAY, /* this is correct, a dict is an array of dict entry */ +  sizeof (TestTypeNodeContainer), +  1, /* number of entries */ +  NULL, +  container_destroy, +  dict_write_value, +  dict_read_value, +  dict_set_value, +  dict_build_signature, +  NULL, +  NULL +}; +  static dbus_bool_t arrays_write_fixed_in_blocks = FALSE;  static const TestTypeNodeClass array_0_class = { @@ -892,7 +920,8 @@ container_nodes[] = {    &struct_2_class,    &array_0_class,    &array_2_class, -  &variant_class +  &variant_class, +  &dict_1_class /* last since we want struct and array before it */    /* array_9_class is omitted on purpose, it's too slow;     * we only use it in one hardcoded test below     */ @@ -2157,8 +2186,8 @@ int16_read_multi (TestTypeNode   *node,    _dbus_assert (n_elements == count);    for (i = 0; i < count; i++) -    _dbus_assert (((int)_dbus_unpack_uint16 (reader->byte_order, -                                             (const unsigned char*)values + (i * 2))) == +    _dbus_assert (((dbus_int16_t)_dbus_unpack_uint16 (reader->byte_order, +                                                      (const unsigned char*)values + (i * 2))) ==                    int16_from_seed (seed + i));    return TRUE; @@ -3298,6 +3327,233 @@ variant_set_value (TestTypeNode   *node,    return variant_read_or_set_value (node, reader, realign_root, seed);  } +static dbus_bool_t +dict_write_value (TestTypeNode   *node, +                  DataBlock      *block, +                  DBusTypeWriter *writer, +                  int             seed) +{ +  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; +  DataBlockState saved; +  DBusTypeWriter sub; +  DBusString entry_value_signature; +  DBusString dict_entry_signature; +  int i; +  int n_entries; +  int entry_value_type; +  TestTypeNode *child; + +  n_entries = node->klass->subclass_detail; + +  _dbus_assert (container->children != NULL); + +  data_block_save (block, &saved); + +  if (!_dbus_string_init (&entry_value_signature)) +    return FALSE; + +  if (!_dbus_string_init (&dict_entry_signature)) +    { +      _dbus_string_free (&entry_value_signature); +      return FALSE; +    } +   +  child = _dbus_list_get_first (&container->children); + +  if (!node_build_signature (child, +                             &entry_value_signature)) +    goto oom; + +  if (!_dbus_string_append (&dict_entry_signature, +                            DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING +                            DBUS_TYPE_INT32_AS_STRING)) +    goto oom; + +  if (!_dbus_string_copy (&entry_value_signature, 0, +                          &dict_entry_signature, +                          _dbus_string_get_length (&dict_entry_signature))) +    goto oom; + +  if (!_dbus_string_append_byte (&dict_entry_signature, +                                 DBUS_DICT_ENTRY_END_CHAR)) +    goto oom; +   +  entry_value_type = _dbus_first_type_in_signature (&entry_value_signature, 0); +   +  if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY, +                                  &dict_entry_signature, 0, +                                  &sub)) +    goto oom; + +  i = 0; +  while (i < n_entries) +    { +      DBusTypeWriter entry_sub; +      dbus_int32_t key; + +      if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_DICT_ENTRY, +                                      NULL, 0, +                                      &entry_sub)) +        goto oom; + +      key = int32_from_seed (seed + i); + +      if (!_dbus_type_writer_write_basic (&entry_sub, +                                          DBUS_TYPE_INT32, +                                          &key)) +        goto oom; +       +      if (!node_write_value (child, block, &entry_sub, seed + i)) +        goto oom; + +      if (!_dbus_type_writer_unrecurse (&sub, &entry_sub)) +        goto oom; +       +      ++i; +    } + +  if (!_dbus_type_writer_unrecurse (writer, &sub)) +    goto oom; +   +  _dbus_string_free (&entry_value_signature); +  _dbus_string_free (&dict_entry_signature); +  return TRUE; + + oom: +  data_block_restore (block, &saved); +  _dbus_string_free (&entry_value_signature); +  _dbus_string_free (&dict_entry_signature); +  return FALSE; +} + +static dbus_bool_t +dict_read_or_set_value (TestTypeNode   *node, +                        DBusTypeReader *reader, +                        DBusTypeReader *realign_root, +                        int             seed) +{ +  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; +  DBusTypeReader sub; +  int i; +  int n_entries; +  TestTypeNode *child; + +  n_entries = node->klass->subclass_detail; + +  check_expected_type (reader, DBUS_TYPE_ARRAY); + +  child = _dbus_list_get_first (&container->children); + +  if (n_entries > 0) +    { +      _dbus_type_reader_recurse (reader, &sub); + +      check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY); +       +      i = 0; +      while (i < n_entries) +        { +          DBusTypeReader entry_sub; + +          check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY); +           +          _dbus_type_reader_recurse (&sub, &entry_sub); +           +          if (realign_root == NULL) +            { +              dbus_int32_t v; +               +              check_expected_type (&entry_sub, DBUS_TYPE_INT32); + +              _dbus_type_reader_read_basic (&entry_sub, +                                            (dbus_int32_t*) &v); + +              _dbus_assert (v == int32_from_seed (seed + i)); + +              NEXT_EXPECTING_TRUE (&entry_sub); +               +              if (!node_read_value (child, &entry_sub, seed + i)) +                return FALSE; + +              NEXT_EXPECTING_FALSE (&entry_sub); +            } +          else +            { +              dbus_int32_t v; +               +              v = int32_from_seed (seed + i); +               +              if (!_dbus_type_reader_set_basic (&entry_sub, +                                                &v, +                                                realign_root)) +                return FALSE; + +              NEXT_EXPECTING_TRUE (&entry_sub); +               +              if (!node_set_value (child, &entry_sub, realign_root, seed + i)) +                return FALSE; + +              NEXT_EXPECTING_FALSE (&entry_sub); +            } +           +          if (i == (n_entries - 1)) +            NEXT_EXPECTING_FALSE (&sub); +          else +            NEXT_EXPECTING_TRUE (&sub); + +          ++i; +        } +    } + +  return TRUE; +} + +static dbus_bool_t +dict_read_value (TestTypeNode   *node, +                 DBusTypeReader *reader, +                 int             seed) +{ +  return dict_read_or_set_value (node, reader, NULL, seed); +} + +static dbus_bool_t +dict_set_value (TestTypeNode   *node, +                DBusTypeReader *reader, +                DBusTypeReader *realign_root, +                int             seed) +{ +  return dict_read_or_set_value (node, reader, realign_root, seed); +} + +static dbus_bool_t +dict_build_signature (TestTypeNode   *node, +                      DBusString     *str) +{ +  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; +  int orig_len; + +  orig_len = _dbus_string_get_length (str); + +  if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY)) +    goto oom; + +  if (!_dbus_string_append (str, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING)) +    goto oom; +   +  if (!node_build_signature (_dbus_list_get_first (&container->children), +                             str)) +    goto oom; + +  if (!_dbus_string_append_byte (str, DBUS_DICT_ENTRY_END_CHAR)) +    goto oom; + +  return TRUE; + + oom: +  _dbus_string_set_length (str, orig_len); +  return FALSE; +} +  static void  container_destroy (TestTypeNode *node)  { 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 */ @@ -461,6 +493,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 */ diff --git a/dbus/dbus-marshal-validate.c b/dbus/dbus-marshal-validate.c index b26adb2c..e57be5c7 100644 --- a/dbus/dbus-marshal-validate.c +++ b/dbus/dbus-marshal-validate.c @@ -40,6 +40,10 @@   * The range passed in should NOT include the terminating   * nul/DBUS_TYPE_INVALID.   * + * @todo verify that dict entries have exactly two fields + *  + * @todo require that dict entries are in an array + *   * @param type_str the string   * @param type_pos where the typecodes start   * @param len length of typecodes @@ -55,6 +59,7 @@ _dbus_validate_signature_with_reason (const DBusString *type_str,    int last;    int struct_depth;    int array_depth; +  int dict_entry_depth;    _dbus_assert (type_str != NULL);    _dbus_assert (type_pos < _DBUS_INT32_MAX - len); @@ -68,6 +73,7 @@ _dbus_validate_signature_with_reason (const DBusString *type_str,    end = _dbus_string_get_const_data_len (type_str, type_pos + len, 0);    struct_depth = 0;    array_depth = 0; +  dict_entry_depth = 0;    last = DBUS_TYPE_INVALID;    while (p != end) @@ -112,7 +118,28 @@ _dbus_validate_signature_with_reason (const DBusString *type_str,            struct_depth -= 1;            break; -        case DBUS_TYPE_STRUCT: /* doesn't appear in signatures */ +        case DBUS_DICT_ENTRY_BEGIN_CHAR: +          if (last != DBUS_TYPE_ARRAY) +            return DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY; +           +          dict_entry_depth += 1; + +          if (dict_entry_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) +            return DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION; +          break; + +        case DBUS_DICT_ENTRY_END_CHAR: +          if (dict_entry_depth == 0) +            return DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED; +           +          if (last == DBUS_DICT_ENTRY_BEGIN_CHAR) +            return DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS; + +          dict_entry_depth -= 1; +          break; +           +        case DBUS_TYPE_STRUCT:     /* doesn't appear in signatures */ +        case DBUS_TYPE_DICT_ENTRY: /* ditto */          default:            return DBUS_INVALID_UNKNOWN_TYPECODE;          } @@ -130,6 +157,9 @@ _dbus_validate_signature_with_reason (const DBusString *type_str,    if (struct_depth > 0)      return DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED; +  if (dict_entry_depth > 0) +    return DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED; +      return DBUS_VALID;  } @@ -377,6 +407,7 @@ validate_body_helper (DBusTypeReader       *reader,            }            break; +        case DBUS_TYPE_DICT_ENTRY:          case DBUS_TYPE_STRUCT:            {              DBusTypeReader sub; diff --git a/dbus/dbus-marshal-validate.h b/dbus/dbus-marshal-validate.h index 94b77989..55739d31 100644 --- a/dbus/dbus-marshal-validate.h +++ b/dbus/dbus-marshal-validate.h @@ -100,7 +100,14 @@ typedef enum    DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES = 46,    DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL = 47,    DBUS_INVALID_STRING_MISSING_NUL = 48, -  DBUS_INVALID_SIGNATURE_MISSING_NUL = 49 +  DBUS_INVALID_SIGNATURE_MISSING_NUL = 49, +  DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION = 50, +  DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED = 51, +  DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED = 52, +  DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS = 53, +  DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD = 54, +  DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS = 55, +  DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY = 56  } DBusValidity;  DBusValidity _dbus_validate_signature_with_reason (const DBusString *type_str, diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 38ae317a..85252005 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -2112,10 +2112,10 @@ dbus_message_iter_append_fixed_array (DBusMessageIter *iter,   * dbus_message_iter_close_container(). Container types are for   * example struct, variant, and array. For variants, the   * contained_signature should be the type of the single value inside - * the variant. For structs, contained_signature should be #NULL; it - * will be set to whatever types you write into the struct.  For - * arrays, contained_signature should be the type of the array - * elements. + * the variant. For structs and dict entries, contained_signature + * should be #NULL; it will be set to whatever types you write into + * the struct.  For arrays, contained_signature should be the type of + * the array elements.   *   * @todo If this fails due to lack of memory, the message is hosed and   * you have to start over building the whole message. @@ -2142,7 +2142,21 @@ dbus_message_iter_open_container (DBusMessageIter *iter,    _dbus_return_val_if_fail (sub != NULL, FALSE);    _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&                               contained_signature == NULL) || +                            (type == DBUS_TYPE_DICT_ENTRY && +                             contained_signature == NULL) ||                              contained_signature != NULL, FALSE); +  _dbus_return_val_if_fail (type != DBUS_TYPE_DICT_ENTRY || +                            dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, +                            FALSE); +   +#if 0 +  /* FIXME this would fail if the contained_signature is a dict entry, +   * since dict entries are invalid signatures standalone (they must be in +   * an array) +   */ +  _dbus_return_val_if_fail (contained_signature == NULL || +                            _dbus_check_is_valid_signature (contained_signature)); +#endif    if (!_dbus_message_iter_open_signature (real))      return FALSE; diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h index d0a3d64e..81912622 100644 --- a/dbus/dbus-protocol.h +++ b/dbus/dbus-protocol.h @@ -77,20 +77,27 @@ extern "C" {  #define DBUS_TYPE_VARIANT       ((int) 'v')  #define DBUS_TYPE_VARIANT_AS_STRING        "v" -/* STRUCT is sort of special since its code can't appear in a type string, - * instead DBUS_STRUCT_BEGIN_CHAR has to appear +/* STRUCT and DICT_ENTRY are sort of special since their codes can't + * appear in a type string, instead + * DBUS_STRUCT_BEGIN_CHAR/DBUS_DICT_ENTRY_BEGIN_CHAR have to appear   */  #define DBUS_TYPE_STRUCT        ((int) 'r')  #define DBUS_TYPE_STRUCT_AS_STRING         "r" +#define DBUS_TYPE_DICT_ENTRY    ((int) 'e') +#define DBUS_TYPE_DICT_ENTRY_AS_STRING     "e"  /* Does not count INVALID */ -#define DBUS_NUMBER_OF_TYPES    (15) +#define DBUS_NUMBER_OF_TYPES    (16)  /* characters other than typecodes that appear in type signatures */  #define DBUS_STRUCT_BEGIN_CHAR   ((int) '(')  #define DBUS_STRUCT_BEGIN_CHAR_AS_STRING   "("  #define DBUS_STRUCT_END_CHAR     ((int) ')')  #define DBUS_STRUCT_END_CHAR_AS_STRING     ")" +#define DBUS_DICT_ENTRY_BEGIN_CHAR   ((int) '{') +#define DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING   "{" +#define DBUS_DICT_ENTRY_END_CHAR     ((int) '}') +#define DBUS_DICT_ENTRY_END_CHAR_AS_STRING     "}"  /* Max length in bytes of a bus name, interface, or member (not object   * path, paths are unlimited). This is limited because lots of stuff @@ -36,14 +36,15 @@ Important for 1.0     yourself; is it an error, or allowed? If allowed,      we need to have a test for it in the test suite. - - array lengths should probably be returned as size_t rather than int -   (though they are kind of a pita to pass in as size_t with the  -    varargs, so maybe not - what does glib do with g_object_get()?) -   - add string array support back to append_args() + - validate dict entry number of fields +   - just before 1.0, try a HAVE_INT64=0 build and be sure it runs + - the spec and implementation should probably require dict keys +   to be basic types +  Important for 1.0 GLib Bindings  === diff --git a/doc/dbus-specification.xml b/doc/dbus-specification.xml index c0be80fb..f72434b3 100644 --- a/doc/dbus-specification.xml +++ b/doc/dbus-specification.xml @@ -7,8 +7,8 @@  <article id="index">    <articleinfo>      <title>D-BUS Specification</title> -    <releaseinfo>Version 0.9</releaseinfo> -    <date>17 January 2005</date> +    <releaseinfo>Version 0.10</releaseinfo> +    <date>28 January 2005</date>      <authorgroup>        <author>  	<firstname>Havoc</firstname> @@ -263,6 +263,28 @@        </para>        <para> +        A <literal>DICT_ENTRY</literal> works exactly like a struct, but rather +        than parentheses it uses curly braces, and it has more restrictions. +        The restrictions are: it occurs only as an array element type; and it +        has exactly two single complete types inside the curly +        braces. Implementations must not accept dict entries outside of arrays, +        and must not accept dict entries with zero, one, or more than two +        fields. A dict entry is always a key-value pair. +      </para> +       +      <para> +        The first field in the <literal>DICT_ENTRY</literal> is always the key. +        A message is considered corrupt if the same key occurs twice in the same +        array of <literal>DICT_ENTRY</literal>. However, for performance reasons +        implementations are not required to reject dicts with duplicate keys. +      </para> + +      <para> +        In most languages, an array of dict entry would be represented as a  +        map, hash table, or dict object. +      </para> + +      <para>          The following table summarizes the D-BUS types.          <informaltable>            <tgroup cols="3"> @@ -287,6 +309,14 @@  		<entry>98 (ASCII 'b')</entry>  		<entry>Boolean value, 0 is <literal>FALSE</literal> and 1 is <literal>TRUE</literal>. Everything else is invalid.</entry>  	      </row><row> +                <entry><literal>INT16</literal></entry> +                <entry>110 (ASCII 'n')</entry> +                <entry>16-bit signed integer</entry> +              </row><row> +                <entry><literal>UINT16</literal></entry> +                <entry>113 (ASCII 'q')</entry> +                <entry>16-bit unsigned integer</entry> +	      </row><row>                  <entry><literal>INT32</literal></entry>                  <entry>105 (ASCII 'i')</entry>                  <entry>32-bit signed integer</entry> @@ -330,6 +360,10 @@                  <entry><literal>VARIANT</literal></entry>                  <entry>118 (ASCII 'v') </entry>                  <entry>Variant type (the type of the value is part of the value itself)</entry> +              </row><row> +                <entry><literal>DICT_ENTRY</literal></entry> +                <entry>101 (ASCII 'e'), 123 (ASCII '{'), 125 (ASCII '}') </entry> +                <entry>Entry in a dict or map (array of key-value pairs)</entry>                </row>              </tbody>            </tgroup> @@ -392,6 +426,14 @@                  <entry>As for <literal>UINT32</literal>, but only 0 and 1 are valid values.</entry>                  <entry>4</entry>                </row><row> +                <entry><literal>INT16</literal></entry> +                <entry>16-bit signed integer in the message's byte order.</entry> +                <entry>2</entry> +              </row><row> +                <entry><literal>UINT16</literal></entry> +                <entry>16-bit unsigned integer in the message's byte order.</entry> +                <entry>2</entry> +              </row><row>                  <entry><literal>INT32</literal></entry>                  <entry>32-bit signed integer in the message's byte order.</entry>                  <entry>4</entry> @@ -478,6 +520,14 @@                  <entry>                    1 (alignment of the signature)                  </entry> +	      </row><row> +                <entry><literal>DICT_ENTRY</literal></entry> +                <entry> +                  Identical to STRUCT. +                </entry> +                <entry> +                  8 +                </entry>  	      </row>              </tbody>            </tgroup>  | 
