diff options
| -rw-r--r-- | dbus/dbus-marshal-basic.c | 77 | ||||
| -rw-r--r-- | dbus/dbus-marshal-basic.h | 21 | ||||
| -rw-r--r-- | dbus/dbus-marshal-recursive.c | 1064 | ||||
| -rw-r--r-- | dbus/dbus-marshal-recursive.h | 78 | ||||
| -rw-r--r-- | dbus/dbus-protocol-new.h | 16 | 
5 files changed, 1103 insertions, 153 deletions
diff --git a/dbus/dbus-marshal-basic.c b/dbus/dbus-marshal-basic.c index d325d5f0..d2b7b404 100644 --- a/dbus/dbus-marshal-basic.c +++ b/dbus/dbus-marshal-basic.c @@ -743,13 +743,25 @@ marshal_8_octets_array (DBusString          *str,  {    int old_string_len;    int array_start; - +      old_string_len = _dbus_string_get_length (str); +  /*  The array length is the length in bytes of the array, +   * *excluding* alignment padding. +   */    if (!_dbus_marshal_uint32 (str, byte_order, len * 8))      goto error;    array_start = _dbus_string_get_length (str); + +  /* Note that we do alignment padding unconditionally +   * even if the array is empty; this means that +   * padding + len is always equal to the number of bytes +   * in the array. +   */ +   +  if (!_dbus_string_align_length (str, 8)) +    goto error;    if (!_dbus_string_append_len (str, (const unsigned char*) value,                                  len * 8)) @@ -1350,6 +1362,9 @@ demarshal_8_octets_array (const DBusString  *str,    int byte_len;    byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); + +  pos = _DBUS_ALIGN_VALUE (pos, 8); +      len = byte_len / 8;    if (len == 0) @@ -1827,6 +1842,8 @@ _dbus_marshal_skip_array (const DBusString  *str,    len = _dbus_demarshal_uint32 (str, byte_order, *pos, pos); +  /* FIXME we need to insert alignment padding according to array type */ +      *pos += len;  } @@ -1897,8 +1914,9 @@ _dbus_marshal_get_arg_end_pos (const DBusString *str,  	/* Demarshal the length  */  	len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); -	 -	*end_pos = pos + len; + +        /* FIXME needs to align to the right boundary for the array type */ +	*end_pos = _DBUS_ALIGN_VALUE (pos, 4) + len;        }        break; @@ -2428,9 +2446,11 @@ _dbus_type_is_valid (int typecode)      case DBUS_TYPE_UINT64:      case DBUS_TYPE_DOUBLE:      case DBUS_TYPE_STRING: +    case DBUS_TYPE_OBJECT_PATH:      case DBUS_TYPE_ARRAY:      case DBUS_TYPE_DICT: -    case DBUS_TYPE_OBJECT_PATH: +    case DBUS_TYPE_STRUCT: +    case DBUS_TYPE_VARIANT:        return TRUE;      default: @@ -2439,16 +2459,59 @@ _dbus_type_is_valid (int typecode)  }  /** + * Gets the alignment requirement for the given type; + * will be 1, 4, or 8. + * + * @param typecode the type + * @returns alignment of 1, 4, or 8 + */ +int +_dbus_type_get_alignment (int typecode) +{ +  switch (typecode) +    { +    case DBUS_TYPE_BYTE: +    case DBUS_TYPE_BOOLEAN: +      return 1; +    case DBUS_TYPE_INT32: +    case DBUS_TYPE_UINT32: +      /* this stuff is 4 since it starts with a length */ +    case DBUS_TYPE_STRING: +    case DBUS_TYPE_OBJECT_PATH: +    case DBUS_TYPE_ARRAY: +    case DBUS_TYPE_DICT: +    case DBUS_TYPE_VARIANT: +      return 4; +    case DBUS_TYPE_INT64: +    case DBUS_TYPE_UINT64: +    case DBUS_TYPE_DOUBLE: +      /* struct is 8 since it could contain an 8-aligned item +       * 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. +       */ +    case DBUS_TYPE_STRUCT: +      return 8; +       +    default: +      _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()"); +      return 0; +    } +} + +/**   * If in verbose mode, print a block of binary data.   *   * @todo right now it prints even if not in verbose mode   *    * @param data the data   * @param len the length of the data + * @param offset where to start counting for byte indexes   */  void  _dbus_verbose_bytes (const unsigned char *data, -                     int                  len) +                     int                  len, +                     int                  offset)  {    int i;    const unsigned char *aligned; @@ -2478,7 +2541,7 @@ _dbus_verbose_bytes (const unsigned char *data,        if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])          {            _dbus_verbose ("%4d\t%p: ", -                         i, &data[i]); +                         offset + i, &data[i]);          }        if (data[i] >= 32 && @@ -2546,7 +2609,7 @@ _dbus_verbose_bytes_of_string (const DBusString    *str,    d = _dbus_string_get_const_data_len (str, start, len); -  _dbus_verbose_bytes (d, len); +  _dbus_verbose_bytes (d, len, start);  }  /** diff --git a/dbus/dbus-marshal-basic.h b/dbus/dbus-marshal-basic.h index e8c0b3fb..968d22cc 100644 --- a/dbus/dbus-marshal-basic.h +++ b/dbus/dbus-marshal-basic.h @@ -53,38 +53,55 @@  #undef DBUS_TYPE_STRUCT  #undef DBUS_NUMBER_OF_TYPES +  /* Never a legitimate type */  #define DBUS_TYPE_INVALID       ((int) '\0') +#define DBUS_TYPE_INVALID_AS_STRING        "\0"  /* Primitive types */  #define DBUS_TYPE_BYTE          ((int) 'y') +#define DBUS_TYPE_BYTE_AS_STRING           "y"  #define DBUS_TYPE_BOOLEAN       ((int) 'b') +#define DBUS_TYPE_BOOLEAN_AS_STRING        "b"  #define DBUS_TYPE_INT32         ((int) 'i') +#define DBUS_TYPE_INT32_AS_STRING          "i"  #define DBUS_TYPE_UINT32        ((int) 'u') +#define DBUS_TYPE_UINT32_AS_STRING         "u"  #define DBUS_TYPE_INT64         ((int) 'x') +#define DBUS_TYPE_INT64_AS_STRING          "x"  #define DBUS_TYPE_UINT64        ((int) 't') +#define DBUS_TYPE_UINT64_AS_STRING         "t"  #define DBUS_TYPE_DOUBLE        ((int) 'd') +#define DBUS_TYPE_DOUBLE_AS_STRING         "d"  #define DBUS_TYPE_STRING        ((int) 's') +#define DBUS_TYPE_STRING_AS_STRING         "s"  #define DBUS_TYPE_OBJECT_PATH   ((int) 'o') +#define DBUS_TYPE_OBJECT_PATH_AS_STRING    "o"  /* Compound types */  #define DBUS_TYPE_ARRAY         ((int) 'a') -#define DBUS_TYPE_DICT          ((int) 'm') +#define DBUS_TYPE_ARRAY_AS_STRING          "a" +#define DBUS_TYPE_DICT          ((int) 'm') /* not parameterized; always map<string,variant> */ +#define DBUS_TYPE_DICT_AS_STRING           "m"  #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   */  #define DBUS_TYPE_STRUCT        ((int) 'r') +#define DBUS_TYPE_STRUCT_AS_STRING         "r"  /* Does not count INVALID */  #define DBUS_NUMBER_OF_TYPES    (13)  /* 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     ")"  static const char *  _hack_dbus_type_to_string (int type) @@ -442,4 +459,6 @@ dbus_bool_t _dbus_marshal_validate_arg    (const DBusString *str,  dbus_bool_t _dbus_type_is_valid           (int               typecode); +int         _dbus_type_get_alignment      (int               typecode); +  #endif /* DBUS_MARSHAL_H */ diff --git a/dbus/dbus-marshal-recursive.c b/dbus/dbus-marshal-recursive.c index 1962e629..5bd37a5a 100644 --- a/dbus/dbus-marshal-recursive.c +++ b/dbus/dbus-marshal-recursive.c @@ -29,6 +29,27 @@   * @{   */ +static int +first_type_in_signature (const DBusString *str, +                         int               pos) +{ +  int 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)); +} +  void  _dbus_type_reader_init (DBusTypeReader    *reader,                          int                byte_order, @@ -42,8 +63,9 @@ _dbus_type_reader_init (DBusTypeReader    *reader,    reader->type_pos = type_pos;    reader->value_str = value_str;    reader->value_pos = value_pos; +  reader->container_type = DBUS_TYPE_INVALID; -  _dbus_verbose ("type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n", +  _dbus_verbose ("  type reader %p init 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));  } @@ -53,17 +75,51 @@ _dbus_type_reader_get_current_type (DBusTypeReader *reader)  {    int t; -  t = _dbus_string_get_byte (reader->type_str, -                             reader->type_pos); +  /* for INVALID t will == DBUS_TYPE_INVALID when we +   * reach the end of type_str, for STRUCT we have to +   * check the finished flag +   */ +  if (reader->container_type == DBUS_TYPE_INVALID) +    { +      t = first_type_in_signature (reader->type_str, +                                   reader->type_pos); +    } +  else if (reader->container_type == DBUS_TYPE_STRUCT) +    { +      if (reader->u.strct.finished) +        t = DBUS_TYPE_INVALID; +      else +        t = first_type_in_signature (reader->type_str, +                                     reader->type_pos); +    } +  else if (reader->container_type == DBUS_TYPE_ARRAY) +    { +      /* return the array element type if elements remain, and +       * TYPE_INVALID otherwise +       */ +      int end_pos; -  if (t == DBUS_STRUCT_BEGIN_CHAR) -    t = DBUS_TYPE_STRUCT; +      end_pos = reader->u.array.start_pos + reader->u.array.len; -  /* this should never be a stopping place */ -  _dbus_assert (t != DBUS_STRUCT_END_CHAR); +      _dbus_assert (reader->value_pos <= end_pos); +      _dbus_assert (reader->value_pos >= reader->u.array.start_pos); + +      if (reader->value_pos < end_pos) +        t = reader->u.array.element_type; +      else +        t = DBUS_TYPE_INVALID; +    } +  else +    { +      _dbus_assert_not_reached ("reader->container_type should not be set to this"); +      t = DBUS_TYPE_INVALID; /* quiet gcc */ +    } +  _dbus_assert (t != DBUS_STRUCT_END_CHAR); +  _dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR); +    #if 0 -  _dbus_verbose ("type reader %p current type_pos = %d type = %s\n", +  _dbus_verbose ("  type reader %p current type_pos = %d type = %s\n",                   reader, reader->type_pos,                   _dbus_type_to_string (t));  #endif @@ -72,44 +128,46 @@ _dbus_type_reader_get_current_type (DBusTypeReader *reader)  }  int -_dbus_type_reader_get_array_type (DBusTypeReader *reader) +_dbus_type_reader_get_array_length (DBusTypeReader *reader)  { -  int t; - -  t = _dbus_type_reader_get_current_type (reader); - -  if (t != DBUS_TYPE_ARRAY) -    return DBUS_TYPE_INVALID; - -  t = _dbus_string_get_byte (reader->type_str, -                             reader->type_pos + 1);   -   -  return t; +  /* FIXME if this is in number of elements I don't know how to compute it +   * since we only have bytes and elements are variable-length +   */  }  void  _dbus_type_reader_read_basic (DBusTypeReader    *reader,                                void              *value)  { -  int t; -  int next; - -  t = _dbus_type_reader_get_current_type (reader); +  if (reader->container_type == DBUS_TYPE_INVALID || +      reader->container_type == DBUS_TYPE_STRUCT || +      reader->container_type == DBUS_TYPE_ARRAY) +    { +      int t; +      int next; +       +      t = _dbus_type_reader_get_current_type (reader); -  next = reader->value_pos; -  _dbus_demarshal_basic_type (reader->value_str, -                              t, value, -                              reader->byte_order, -                              &next); +      next = reader->value_pos; +      _dbus_demarshal_basic_type (reader->value_str, +                                  t, value, +                                  reader->byte_order, +                                  &next); -  _dbus_verbose ("type reader %p read basic type_pos = %d value_pos = %d next = %d remaining sig '%s'\n", -                 reader, reader->type_pos, reader->value_pos, next, -                 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0)); -  _dbus_verbose_bytes_of_string (reader->value_str, -                                 reader->value_pos, -                                 MIN (16, -                                      _dbus_string_get_length (reader->value_str) - reader->value_pos)); +      _dbus_verbose ("  type reader %p read basic type_pos = %d value_pos = %d next = %d remaining sig '%s'\n", +                     reader, reader->type_pos, reader->value_pos, next, +                     _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0)); +       +      _dbus_verbose_bytes_of_string (reader->value_str, +                                     reader->value_pos, +                                     MIN (16, +                                          _dbus_string_get_length (reader->value_str) - reader->value_pos)); +    } +  else +    { +      _dbus_assert_not_reached ("reader->container_type should not be set to this"); +    }  }  dbus_bool_t @@ -136,7 +194,17 @@ _dbus_type_reader_recurse (DBusTypeReader *reader,  {    int t; -  t = _dbus_string_get_byte (reader->type_str, reader->type_pos); +  /* FIXME are we recursing over the type signature or over the values. +   * Arrays don't necessarily have values for each element of the type +   * signature. Thus we get a mismatch where we need to "bail out" and +   * return the signature of each element, but can't return an element +   * or recurse into the element signature. Not sure how to handle this; +   * maybe think about how we will handle variant types and do something +   * similar since they also have the idea of a signature for the whole +   * sub-item? +   */ +   +  t = first_type_in_signature (reader->type_str, reader->type_pos);    /* point subreader at the same place as reader */    _dbus_type_reader_init (sub, @@ -146,17 +214,99 @@ _dbus_type_reader_recurse (DBusTypeReader *reader,                            reader->value_str,                            reader->value_pos); -  _dbus_assert (t == DBUS_STRUCT_BEGIN_CHAR); /* only this works right now */ -   -  sub->type_pos += 1; +  if (t == DBUS_TYPE_STRUCT) +    { +      sub->container_type = DBUS_TYPE_STRUCT; +       +      sub->type_pos += 1; + +      /* struct has 8 byte alignment */ +      sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8); + +      sub->u.strct.finished = FALSE; +    } +  else if (t == DBUS_TYPE_ARRAY) +    { +      dbus_uint32_t array_len; +      int alignment; + +      sub->container_type = DBUS_TYPE_ARRAY; +       +      /* point type_pos at the array element type */ +      sub->type_pos += 1; + +      sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4); +       +      _dbus_demarshal_basic_type (sub->value_str, +                                  DBUS_TYPE_UINT32, +                                  &array_len, +                                  sub->byte_order, +                                  &sub->value_pos); +       +      sub->u.array.len = array_len; +       +      alignment = element_type_get_alignment (sub->type_str, +                                              sub->type_pos); +       +      sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment); + +      sub->u.array.element_type = first_type_in_signature (sub->type_str, +                                                           sub->type_pos); +      sub->u.array.start_pos = sub->value_pos; -  /* no value_pos increment since the struct itself doesn't take up value space */ +      _dbus_verbose ("    type reader %p array start = %d array len = %d array element type = %s\n", +                     reader, +                     sub->u.array.start_pos, +                     sub->u.array.len, +                     _dbus_type_to_string (sub->u.array.element_type)); +    } +  else +    { +      _dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t)); +      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_assert_not_reached ("don't yet handle recursing into this type"); +    } -  _dbus_verbose ("type reader %p recursed type_pos = %d value_pos = %d remaining sig '%s'\n", +  _dbus_verbose ("  type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",                   sub, sub->type_pos, sub->value_pos,                   _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));  } +static void +skip_one_complete_type (const DBusString *type_str, +                        int              *type_pos) +{ +  while (_dbus_string_get_byte (type_str, *type_pos) == DBUS_TYPE_ARRAY) +    *type_pos += 1; + +  if (_dbus_string_get_byte (type_str, *type_pos) == DBUS_STRUCT_BEGIN_CHAR) +    { +      int depth; +      depth = 1; +      *type_pos += 1; +      while (depth > 0) +        { +          switch (_dbus_string_get_byte (type_str, *type_pos)) +            { +            case DBUS_STRUCT_BEGIN_CHAR: +              depth += 1; +              break; +            case DBUS_STRUCT_END_CHAR: +              depth -= 1; +              break; +            case DBUS_TYPE_INVALID: +              _dbus_assert_not_reached ("unbalanced parens in signature"); +              break; +            } +          *type_pos += 1; +        } +    } +  else +    *type_pos += 1; +} +  /**   * Skip to the next value on this "level". e.g. the next field in a   * struct, the next value in an array, the next key or value in a @@ -169,65 +319,122 @@ dbus_bool_t  _dbus_type_reader_next (DBusTypeReader *reader)  {    int t; - -  /* FIXME handled calling next when there's no next */ -  t = _dbus_string_get_byte (reader->type_str, reader->type_pos); +  t = _dbus_type_reader_get_current_type (reader); -  _dbus_verbose ("type reader %p next() { type_pos = %d value_pos = %d remaining sig '%s'\n", +  _dbus_verbose ("  type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",                   reader, reader->type_pos, reader->value_pos, -                 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0)); +                 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0), +                 _dbus_type_to_string (t)); + +  if (t == DBUS_TYPE_INVALID) +    return FALSE; -  switch (t) +  if (reader->container_type == DBUS_TYPE_INVALID || +      reader->container_type == DBUS_TYPE_STRUCT)      { -    case DBUS_STRUCT_BEGIN_CHAR: -      /* Scan forward over the entire container contents */ -      { -        DBusTypeReader sub; - -        /* Recurse into the struct */ -        _dbus_type_reader_recurse (reader, &sub); - -        /* Skip everything in this subreader */ -        while (_dbus_type_reader_next (&sub)) +      switch (t) +        { +        case DBUS_TYPE_STRUCT: +        case DBUS_TYPE_ARRAY: +          /* Scan forward over the entire container contents */ +          /* FIXME this is super slow for arrays. We need to special +           * case skipping all the elements at once instead of scanning. +           */            { -            /* nothing */; -          } +            DBusTypeReader sub; -        /* Now we are at the end of this container */ -        reader->type_pos = sub.type_pos; -        reader->value_pos = sub.value_pos; -      } -      break; +            /* Recurse into the struct */ +            _dbus_type_reader_recurse (reader, &sub); -    default: -      /* FIXME for array etc. this is more complicated */ -      _dbus_marshal_skip_basic_type (reader->value_str, -                                     t, reader->byte_order, -                                     &reader->value_pos); -      reader->type_pos += 1; -      break; -    } - -  _dbus_verbose ("type reader %p }  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)); - -  /* FIXME this is wrong; we need to return FALSE when we finish the -   * container we've recursed into; even if the signature continues. -   */ -   -  t = _dbus_string_get_byte (reader->type_str, reader->type_pos); +            /* Skip everything in this subreader */ +            while (_dbus_type_reader_next (&sub)) +              { +                /* nothing */; +              } -  if (t == DBUS_STRUCT_END_CHAR) +            /* Now we are at the end of this container */ +            reader->type_pos = sub.type_pos; +            reader->value_pos = sub.value_pos; +          } +          break; + +        default: +          _dbus_marshal_skip_basic_type (reader->value_str, +                                         t, reader->byte_order, +                                         &reader->value_pos); +          reader->type_pos += 1; +          break; +        } + +      /* 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()) +       */ +      if (reader->container_type == DBUS_TYPE_STRUCT) +        { +          t = _dbus_string_get_byte (reader->type_str, reader->type_pos); +          if (t == DBUS_STRUCT_END_CHAR) +            { +              reader->type_pos += 1; +              reader->u.strct.finished = TRUE; +            } +        } +    } +  else if (reader->container_type == DBUS_TYPE_ARRAY)      { -      reader->type_pos += 1; -      return FALSE; +      /* Skip one array element */ +      int end_pos; + +      end_pos = reader->u.array.start_pos + reader->u.array.len; + +      _dbus_assert (reader->value_pos < end_pos); +      _dbus_assert (reader->value_pos >= reader->u.array.start_pos); + +      if (reader->u.array.element_type == DBUS_TYPE_ARRAY || +          reader->u.array.element_type == DBUS_TYPE_STRUCT) +        { +          DBusTypeReader sub; +           +          /* Recurse into the array element */ +          _dbus_type_reader_recurse (reader, &sub); + +            /* Skip everything in this element */ +          while (_dbus_type_reader_next (&sub)) +            { +              /* nothing */; +            } + +          /* Now we are at the end of this element */ +          reader->value_pos = sub.value_pos; +        } +      else +        { +          _dbus_marshal_skip_basic_type (reader->value_str, +                                         t, reader->byte_order, +                                         &reader->value_pos); +        } + +      _dbus_assert (reader->value_pos <= end_pos); +       +      if (reader->value_pos == end_pos) +        { +          skip_one_complete_type (reader->type_str, +                                  &reader->type_pos); +        } +    } +  else +    { +      _dbus_assert_not_reached ("reader->container_type should not be set to this");      } -  if (t == DBUS_TYPE_INVALID) -    return FALSE; -  return TRUE; +  _dbus_verbose ("  type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n", +                 reader, reader->type_pos, reader->value_pos, +                 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0), +                 _dbus_type_to_string (_dbus_type_reader_get_current_type (reader))); +   +  return _dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID;  }  void @@ -244,6 +451,31 @@ _dbus_type_writer_init (DBusTypeWriter *writer,    writer->value_str = value_str;    writer->value_pos = value_pos;    writer->container_type = DBUS_TYPE_INVALID; +  writer->inside_array = FALSE; +} + +static dbus_bool_t +_dbus_type_writer_write_basic_no_typecode (DBusTypeWriter *writer, +                                           int             type, +                                           const void     *value) +{ +  int old_value_len; +  int bytes_written; + +  old_value_len = _dbus_string_get_length (writer->value_str); +         +  if (!_dbus_marshal_basic_type (writer->value_str, +                                 writer->value_pos, +                                 type, +                                 value, +                                 writer->byte_order)) +    return FALSE; + +  bytes_written = _dbus_string_get_length (writer->value_str) - old_value_len; +   +  writer->value_pos += bytes_written; + +  return TRUE;  }  dbus_bool_t @@ -252,36 +484,33 @@ _dbus_type_writer_write_basic (DBusTypeWriter *writer,                                 const void     *value)  {    dbus_bool_t retval; -  int old_value_len; - -  old_value_len = _dbus_string_get_length (writer->value_str);    /* First ensure that our type realloc will succeed */    if (!_dbus_string_alloc_space (writer->type_str, 1))      return FALSE;    retval = FALSE; -         -  if (!_dbus_marshal_basic_type (writer->value_str, -                                 writer->value_pos, -                                 type, -                                 value, -                                 writer->byte_order)) -    goto out; -  writer->value_pos += _dbus_string_get_length (writer->value_str) - old_value_len; +  if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value)) +    goto out; -  /* Now insert the type */ -  if (!_dbus_string_insert_byte (writer->type_str, -                                 writer->type_pos, -                                 type)) -    _dbus_assert_not_reached ("failed to insert byte after prealloc"); - -  writer->type_pos += 1; +  /* Now insert the type unless we're already covered by the array signature */ +  if (!writer->inside_array) +    { +      if (!_dbus_string_insert_byte (writer->type_str, +                                     writer->type_pos, +                                     type)) +        _dbus_assert_not_reached ("failed to insert byte after prealloc"); +       +      writer->type_pos += 1; +    }    retval = TRUE;   out: +  _dbus_verbose ("  type writer %p basic type_pos = %d value_pos = %d inside_array = %d\n", +                 writer, writer->type_pos, writer->value_pos, writer->inside_array); +      return retval;  } @@ -295,10 +524,11 @@ _dbus_type_writer_write_array (DBusTypeWriter *writer,  } -dbus_bool_t -_dbus_type_writer_recurse (DBusTypeWriter *writer, -                           int             container_type, -                           DBusTypeWriter *sub) +static void +writer_recurse_init_and_check (DBusTypeWriter *writer, +                               int             container_type, +                               const char     *array_element_type, +                               DBusTypeWriter *sub)  {    _dbus_type_writer_init (sub,                            writer->byte_order, @@ -306,20 +536,113 @@ _dbus_type_writer_recurse (DBusTypeWriter *writer,                            writer->type_pos,                            writer->value_str,                            writer->value_pos); +      sub->container_type = container_type; + +  /* While inside an array, we never want to write to the type str. +   * We are inside an array if we're currently recursing into one. +   */ +  if (writer->inside_array || sub->container_type == DBUS_TYPE_ARRAY) +    sub->inside_array = TRUE; +  else +    sub->inside_array = FALSE; + +  /* If our parent is an array, things are a little bit complicated. +   * +   * The parent must have a complete element type, such as +   * "i" or "aai" or "(ii)" or "a(ii)". There can't be +   * unclosed parens, or an "a" with no following type. +   * +   * To recurse, the only allowed operation is to recurse into the +   * first type in the element type. So for "i" you can't recurse, for +   * "ai" you can recurse into the array, for "(ii)" you can recurse +   * into the struct. +   * +   * If you recurse into the array for "ai", then you must specify +   * "i" for the element type of the array you recurse into. +   *  +   * While inside an array at any level, we need to avoid writing to +   * type_str, since the type only appears once for the whole array, +   * it does not appear for each array element. +   */ +#ifndef DBUS_DISABLE_CHECKS +  if (writer->container_type == DBUS_TYPE_ARRAY) +    { +      if ((sub->container_type == DBUS_TYPE_STRUCT && +           writer->u.array.element_type[0] != DBUS_STRUCT_BEGIN_CHAR) || +          (sub->container_type != DBUS_TYPE_STRUCT && +           writer->u.array.element_type[0] != sub->container_type)) +        { +          _dbus_warn ("Recursing into an array with element type %s not allowed with container type %s\n", +                      writer->u.array.element_type, _dbus_type_to_string (sub->container_type)); +        } + +      if (sub->container_type == DBUS_TYPE_ARRAY) +        { +          DBusString parent_elements; +          DBusString our_elements; + +          _dbus_assert (writer->u.array.element_type[0] == DBUS_TYPE_ARRAY); +           +          _dbus_string_init_const (&parent_elements, &writer->u.array.element_type[1]); +          _dbus_string_init_const (&our_elements, array_element_type); + +          if (!_dbus_string_equal (&parent_elements, &our_elements)) +            { +              _dbus_warn ("Parent array expects elements '%s' and we are writing an array of '%s'\n", +                          writer->u.array.element_type, +                          array_element_type); +            } +        } +    } +#endif /* DBUS_DISABLE_CHECKS */ + +  _dbus_verbose ("  type writer %p recurse type_pos = %d value_pos = %d inside_array = %d container_type = %s\n", +                 writer, writer->type_pos, writer->value_pos, writer->inside_array, +                 _dbus_type_to_string (writer->container_type)); +  _dbus_verbose ("  type writer %p new sub type_pos = %d value_pos = %d inside_array = %d container_type = %s element_type = '%s'\n", +                 sub, sub->type_pos, sub->value_pos, +                 sub->inside_array, +                 _dbus_type_to_string (sub->container_type), +                 array_element_type ? array_element_type : "n/a"); +} + +dbus_bool_t +_dbus_type_writer_recurse (DBusTypeWriter *writer, +                           int             container_type, +                           DBusTypeWriter *sub) +{ +  writer_recurse_init_and_check (writer, container_type, NULL, sub);    switch (container_type)      {      case DBUS_TYPE_STRUCT:        { -        if (!_dbus_string_insert_byte (sub->type_str, -                                       sub->type_pos, -                                       DBUS_STRUCT_BEGIN_CHAR)) -          return FALSE; +        if (!writer->inside_array) +          { +            /* Ensure that we'll be able to add alignment padding */ +            if (!_dbus_string_alloc_space (sub->value_str, 8)) +              return FALSE; +             +            if (!_dbus_string_insert_byte (sub->type_str, +                                           sub->type_pos, +                                           DBUS_STRUCT_BEGIN_CHAR)) +              return FALSE; + +            sub->type_pos += 1; +          } -        sub->type_pos += 1; +        if (!_dbus_string_insert_bytes (sub->value_str, +                                        sub->value_pos, +                                        _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos, +                                        '\0')) +          _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct"); +        sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);        }        break; +    case DBUS_TYPE_ARRAY: +      _dbus_assert_not_reached ("use recurse_array() for arrays"); +      break;      default:        _dbus_assert_not_reached ("container_type unhandled");        break; @@ -329,18 +652,130 @@ _dbus_type_writer_recurse (DBusTypeWriter *writer,  }  dbus_bool_t +_dbus_type_writer_recurse_array (DBusTypeWriter *writer, +                                 const char     *element_type, +                                 DBusTypeWriter *sub) +{ +  int element_type_len; +  DBusString element_type_str; +   +  writer_recurse_init_and_check (writer, DBUS_TYPE_ARRAY, element_type, sub); + +  _dbus_string_init_const (&element_type_str, element_type); +  element_type_len = _dbus_string_get_length (&element_type_str); + +  /* 4 bytes for the array length and 4 bytes possible padding */ +  if (!_dbus_string_alloc_space (sub->value_str, 8)) +    return FALSE; + +  if (!writer->inside_array) +    { +      /* alloc space for array typecode, element signature, possible 7 +       * bytes of padding +       */ +      if (!_dbus_string_alloc_space (sub->type_str, 1 + element_type_len + 7)) +        return FALSE; +    } +       +  if (!_dbus_string_copy_data (&element_type_str, +                               &sub->u.array.element_type)) +    return FALSE; + +  if (!writer->inside_array) +    { +      if (!_dbus_string_insert_byte (sub->type_str, +                                     sub->type_pos, +                                     DBUS_TYPE_ARRAY)) +        _dbus_assert_not_reached ("should not have failed to insert array typecode"); + +      sub->type_pos += 1; +       +      if (!_dbus_string_copy (&element_type_str, 0, +                              sub->type_str, sub->type_pos)) +        _dbus_assert_not_reached ("should not have failed to insert array element typecodes"); +   +      sub->type_pos += element_type_len; +    } +   +  sub->u.array.len_pos = sub->value_pos; + +  { +    dbus_uint32_t value = 0; +    int alignment; +    int aligned; +    DBusString str; +     +    if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32, +                                                    &value)) +      _dbus_assert_not_reached ("should not have failed to insert array len"); + +    _dbus_string_init_const (&str, element_type); +    alignment = element_type_get_alignment (&str, 0); + +    aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment); +    if (aligned != sub->value_pos) +      { +        if (!_dbus_string_insert_bytes (sub->value_str, +                                        sub->value_pos, +                                        aligned - sub->value_pos, +                                        '\0')) +          _dbus_assert_not_reached ("should not have failed to insert alignment padding"); + +        sub->value_pos = aligned; +      } +    sub->u.array.start_pos = sub->value_pos; +  } + +  _dbus_assert (sub->u.array.start_pos == sub->value_pos); +  _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos); +   +  /* value_pos now points to the place for array data, and len_pos to the length */ + +  return TRUE; +} + +dbus_bool_t  _dbus_type_writer_unrecurse (DBusTypeWriter *writer,                               DBusTypeWriter *sub)  {    _dbus_assert (sub->type_pos > 0); /* can't be recursed if this fails */ +  _dbus_verbose ("  type writer %p unrecurse type_pos = %d value_pos = %d inside_array = %d container_type = %s\n", +                 writer, writer->type_pos, writer->value_pos, writer->inside_array, +                 _dbus_type_to_string (writer->container_type)); +  _dbus_verbose ("  type writer %p unrecurse sub type_pos = %d value_pos = %d inside_array = %d container_type = %s element_type = '%s'\n", +                 sub, sub->type_pos, sub->value_pos, +                 sub->inside_array, +                 _dbus_type_to_string (sub->container_type), +                 sub->container_type == DBUS_TYPE_ARRAY ? +                 sub->u.array.element_type : "n/a"); +      if (sub->container_type == DBUS_TYPE_STRUCT)      { -      if (!_dbus_string_insert_byte (sub->type_str, -                                     sub->type_pos,  -                                     DBUS_STRUCT_END_CHAR)) -        return FALSE; -      sub->type_pos += 1; +      if (!sub->inside_array) +        { +          if (!_dbus_string_insert_byte (sub->type_str, +                                         sub->type_pos,  +                                         DBUS_STRUCT_END_CHAR)) +            return FALSE; +          sub->type_pos += 1; +        } +    } +  else if (sub->container_type == DBUS_TYPE_ARRAY) +    { +      dbus_uint32_t len; +       +      dbus_free (sub->u.array.element_type); +      sub->u.array.element_type = NULL; + +      /* Set the array length */ +      len = sub->value_pos - sub->u.array.start_pos; +      _dbus_marshal_set_uint32 (sub->value_str, +                                sub->byte_order, +                                sub->u.array.len_pos, +                                len); +      _dbus_verbose ("    filled in sub array len to %u at len_pos %d\n", +                     len, sub->u.array.len_pos);      }    /* Jump the parent writer to the new location */ @@ -672,12 +1107,325 @@ read_struct_of_structs_of_structs (DataBlock      *block,    return TRUE;  } +static dbus_bool_t +write_array_of_int32 (DataBlock      *block, +                      DBusTypeWriter *writer) +{ +  dbus_int32_t v; +  DataBlockState saved; +  DBusTypeWriter sub; + +  data_block_save (block, &saved); +   +  if (!_dbus_type_writer_recurse_array (writer, +                                        DBUS_TYPE_INT32_AS_STRING, +                                        &sub)) +    return FALSE; + +  v = SAMPLE_INT32_ALTERNATE; +  if (!_dbus_type_writer_write_basic (&sub, +                                      DBUS_TYPE_INT32, +                                      &v)) +    { +      data_block_restore (block, &saved); +      return FALSE; +    } + +  v = SAMPLE_INT32; +  if (!_dbus_type_writer_write_basic (&sub, +                                      DBUS_TYPE_INT32, +                                      &v)) +    { +      data_block_restore (block, &saved); +      return FALSE; +    } + +  v = SAMPLE_INT32; +  if (!_dbus_type_writer_write_basic (&sub, +                                      DBUS_TYPE_INT32, +                                      &v)) +    { +      data_block_restore (block, &saved); +      return FALSE; +    } +   +  if (!_dbus_type_writer_unrecurse (writer, &sub)) +    { +      data_block_restore (block, &saved); +      return FALSE; +    } +   +  return TRUE; +} + +static dbus_bool_t +read_array_of_int32 (DataBlock      *block, +                     DBusTypeReader *reader) +{ +  dbus_int32_t v; +  DBusTypeReader sub; + +  check_expected_type (reader, DBUS_TYPE_ARRAY); +   +  _dbus_type_reader_recurse (reader, &sub); + +  check_expected_type (&sub, DBUS_TYPE_INT32); +   +  _dbus_type_reader_read_basic (&sub, +                                (dbus_int32_t*) &v); + +  _dbus_assert (v == SAMPLE_INT32_ALTERNATE); + +  _dbus_type_reader_next (&sub); +  check_expected_type (&sub, DBUS_TYPE_INT32); +   +  _dbus_type_reader_read_basic (&sub, +                                (dbus_int32_t*) &v); + +  _dbus_assert (v == SAMPLE_INT32); + +  _dbus_type_reader_next (&sub); +  check_expected_type (&sub, DBUS_TYPE_INT32); +   +  _dbus_type_reader_read_basic (&sub, +                                (dbus_int32_t*) &v); + +  _dbus_assert (v == SAMPLE_INT32); +   +  return TRUE; +} + + +static dbus_bool_t +write_array_of_int32_empty (DataBlock      *block, +                            DBusTypeWriter *writer) +{ +  DataBlockState saved; +  DBusTypeWriter sub; + +  data_block_save (block, &saved); +   +  if (!_dbus_type_writer_recurse_array (writer, +                                        DBUS_TYPE_INT32_AS_STRING, +                                        &sub)) +    return FALSE; +   +  if (!_dbus_type_writer_unrecurse (writer, &sub)) +    { +      data_block_restore (block, &saved); +      return FALSE; +    } +   +  return TRUE; +} + +static dbus_bool_t +read_array_of_int32_empty (DataBlock      *block, +                           DBusTypeReader *reader) +{ +  DBusTypeReader sub; + +  check_expected_type (reader, DBUS_TYPE_ARRAY); +   +  _dbus_type_reader_recurse (reader, &sub); + +  check_expected_type (&sub, DBUS_TYPE_INVALID); +   +  return TRUE; +} + +static dbus_bool_t +write_array_of_array_of_int32 (DataBlock      *block, +                               DBusTypeWriter *writer) +{ +  DataBlockState saved; +  DBusTypeWriter sub; + +  data_block_save (block, &saved); +   +  if (!_dbus_type_writer_recurse_array (writer, +                                        DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING, +                                        &sub)) +    return FALSE; + +  if (!write_array_of_int32 (block, &sub)) +    { +      data_block_restore (block, &saved); +      return FALSE; +    } + +  if (!write_array_of_int32 (block, &sub)) +    { +      data_block_restore (block, &saved); +      return FALSE; +    } + +  if (!write_array_of_int32_empty (block, &sub)) +    { +      data_block_restore (block, &saved); +      return FALSE; +    } +   +  if (!write_array_of_int32 (block, &sub)) +    { +      data_block_restore (block, &saved); +      return FALSE; +    } +   +  if (!_dbus_type_writer_unrecurse (writer, &sub)) +    { +      data_block_restore (block, &saved); +      return FALSE; +    } +   +  return TRUE; +} + +static dbus_bool_t +read_array_of_array_of_int32 (DataBlock      *block, +                              DBusTypeReader *reader) +{ +  DBusTypeReader sub; +   +  check_expected_type (reader, DBUS_TYPE_ARRAY); +   +  _dbus_type_reader_recurse (reader, &sub); + +  if (!read_array_of_int32 (block, &sub)) +    return FALSE; +  _dbus_type_reader_next (&sub); +  if (!read_array_of_int32 (block, &sub)) +    return FALSE; +  _dbus_type_reader_next (&sub); +  if (!read_array_of_int32_empty (block, &sub)) +    return FALSE; +  _dbus_type_reader_next (&sub); +  if (!read_array_of_int32 (block, &sub)) +    return FALSE; +  _dbus_type_reader_next (&sub); +   +  return TRUE; +} + + +static dbus_bool_t +write_array_of_array_of_int32_empty (DataBlock      *block, +                                     DBusTypeWriter *writer) +{ +  DataBlockState saved; +  DBusTypeWriter sub; + +  data_block_save (block, &saved); +   +  if (!_dbus_type_writer_recurse_array (writer, +                                        DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING, +                                        &sub)) +    return FALSE; + +  if (!_dbus_type_writer_unrecurse (writer, &sub)) +    { +      data_block_restore (block, &saved); +      return FALSE; +    } +   +  return TRUE; +} + +static dbus_bool_t +read_array_of_array_of_int32_empty (DataBlock      *block, +                                    DBusTypeReader *reader) +{ +  DBusTypeReader sub; +  DBusTypeReader sub2; +   +  check_expected_type (reader, DBUS_TYPE_ARRAY); +   +  _dbus_type_reader_recurse (reader, &sub); + +  check_expected_type (reader, DBUS_TYPE_ARRAY); + +  _dbus_type_reader_recurse (&sub, &sub2); + +  check_expected_type (reader, DBUS_TYPE_INVALID); +   +  return TRUE; +} + +static dbus_bool_t +write_array_of_array_of_array_of_int32 (DataBlock      *block, +                                        DBusTypeWriter *writer) +{ +  DataBlockState saved; +  DBusTypeWriter sub; + +  data_block_save (block, &saved); +   +  if (!_dbus_type_writer_recurse_array (writer, +                                        DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING, +                                        &sub)) +    return FALSE; + +  if (!write_array_of_array_of_int32 (block, &sub)) +    { +      data_block_restore (block, &saved); +      return FALSE; +    } + +  if (!write_array_of_array_of_int32 (block, &sub)) +    { +      data_block_restore (block, &saved); +      return FALSE; +    } + +  if (!write_array_of_array_of_int32_empty (block, &sub)) +    { +      data_block_restore (block, &saved); +      return FALSE; +    } +   +  if (!_dbus_type_writer_unrecurse (writer, &sub)) +    { +      data_block_restore (block, &saved); +      return FALSE; +    } +   +  return TRUE; +} + +static dbus_bool_t +read_array_of_array_of_array_of_int32 (DataBlock      *block, +                                       DBusTypeReader *reader) +{ +  DBusTypeReader sub; +   +  check_expected_type (reader, DBUS_TYPE_ARRAY); +   +  _dbus_type_reader_recurse (reader, &sub); + +  if (!read_array_of_array_of_int32 (block, &sub)) +    return FALSE; +  _dbus_type_reader_next (&sub); +  if (!read_array_of_array_of_int32 (block, &sub)) +    return FALSE; +  _dbus_type_reader_next (&sub); +  if (!read_array_of_array_of_int32_empty (block, &sub)) +    return FALSE; +  _dbus_type_reader_next (&sub); +   +  return TRUE; +} +  typedef enum {    ITEM_INVALID = -1,    ITEM_INT32 = 0,    ITEM_STRUCT_WITH_INT32S,    ITEM_STRUCT_OF_STRUCTS,    ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, +  ITEM_ARRAY_OF_INT32, +  ITEM_ARRAY_OF_INT32_EMPTY, +  ITEM_ARRAY_OF_ARRAY_OF_INT32, +  ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY, +  ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,    ITEM_LAST  } WhichItem; @@ -705,12 +1453,25 @@ static CheckMarshalItem items[] = {    { "struct of two structs of three structs of two int32",      ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,      write_struct_of_structs_of_structs, -    read_struct_of_structs_of_structs } +    read_struct_of_structs_of_structs }, +  { "array of int32", +    ITEM_ARRAY_OF_INT32, write_array_of_int32, read_array_of_int32 }, +  { "empty array of int32", +    ITEM_ARRAY_OF_INT32_EMPTY, write_array_of_int32_empty, read_array_of_int32_empty }, +  { "array of array of int32", +    ITEM_ARRAY_OF_ARRAY_OF_INT32, +    write_array_of_array_of_int32, read_array_of_array_of_int32 }, +  { "empty array of array of int32", +    ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY, +    write_array_of_array_of_int32_empty, read_array_of_array_of_int32_empty }, +  { "array of array of array of int32", +    ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, +    write_array_of_array_of_array_of_int32, read_array_of_array_of_array_of_int32 }  };  typedef struct  { -  /* Array of items in the above items[]; -1 terminated */ +  /* Array of items from the above items[]; -1 terminated */    int items[20];  } TestRun; @@ -743,7 +1504,44 @@ static TestRun runs[] = {    { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },    { { ITEM_STRUCT_WITH_INT32S, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },    { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } }, -  { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } } +  { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } }, + +  /* ARRAY_OF_INT32 */ +  { { ITEM_ARRAY_OF_INT32, ITEM_INVALID } }, +  { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } }, +  { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } }, +  { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } }, +  { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } }, +  { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } }, +  { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } }, +  { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } }, +  { { ITEM_STRUCT_WITH_INT32S, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } }, +  { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } }, + +  /* ARRAY_OF_ARRAY_OF_INT32 */ +  { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } }, +  { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } }, +  { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } }, +  { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } }, +  { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } }, +  { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } }, +  { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } }, +  { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } }, +  { { ITEM_STRUCT_WITH_INT32S, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } }, +  { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } }, + +  /* ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32 */ +  { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } }, +  { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } }, +  { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } }, +  { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } }, +  { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } }, +  { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } }, +  { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } }, +  { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } }, +  { { ITEM_STRUCT_WITH_INT32S, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } }, +  { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } } +  }; @@ -760,6 +1558,20 @@ perform_one_run (DataBlock *block,    retval = FALSE; +  { +    _dbus_verbose ("run byteorder %s items ", +                   byte_order == DBUS_LITTLE_ENDIAN ? "little" : "big"); +    i = 0; +    while (run->items[i] != ITEM_INVALID) +      { +        CheckMarshalItem *item = &items[run->items[i]]; +         +        _dbus_verbose ("%s ", item->desc); +        ++i; +      } +    _dbus_verbose (" = %d items\n", i); +  } +      data_block_save (block, &saved);    data_block_init_reader_writer (block,  @@ -771,7 +1583,7 @@ perform_one_run (DataBlock *block,      {        CheckMarshalItem *item = &items[run->items[i]]; -      _dbus_verbose ("writing %s\n", item->desc); +      _dbus_verbose (">>writing %s\n", item->desc);        if (!(* item->write_item_func) (block, &writer))          goto out; @@ -783,7 +1595,7 @@ perform_one_run (DataBlock *block,      {        CheckMarshalItem *item = &items[run->items[i]]; -      _dbus_verbose ("reading %s\n", item->desc); +      _dbus_verbose (">>reading %s\n", item->desc);        if (!(* item->read_item_func) (block, &reader))          goto out; diff --git a/dbus/dbus-marshal-recursive.h b/dbus/dbus-marshal-recursive.h index ed70a827..57b55fcf 100644 --- a/dbus/dbus-marshal-recursive.h +++ b/dbus/dbus-marshal-recursive.h @@ -56,6 +56,26 @@ struct DBusTypeReader    int type_pos;    const DBusString *value_str;    int value_pos; + +  /* Hmm - it might be cleaner to do TypeReaderClass *vtable for container type */ +  int container_type; +  union +  { +    struct { +      int start_pos; +      dbus_uint32_t len; +      int element_type; +    } array; + +    struct { +      int len_pos; + +    } dict; + +    struct { +      dbus_uint32_t finished : 1; +    } strct; +  } u;  };  typedef struct DBusTypeReader DBusTypeReader; @@ -67,7 +87,23 @@ struct DBusTypeWriter    int type_pos;    DBusString *value_str;    int value_pos; + +  dbus_uint32_t inside_array : 1; +    int container_type; +  union +  { +    struct { +      int start_pos; /* first element */ +      int len_pos; +      char *element_type; +    } array; + +    struct { +      int len_pos; + +    } dict; +  } u;  };  typedef struct DBusTypeWriter DBusTypeWriter; @@ -79,7 +115,7 @@ void        _dbus_type_reader_init                (DBusTypeReader    *reader,                                                     const DBusString  *value_str,                                                     int                value_pos);  int         _dbus_type_reader_get_current_type    (DBusTypeReader    *reader); -int         _dbus_type_reader_get_array_type      (DBusTypeReader    *reader); +int         _dbus_type_reader_get_array_length    (DBusTypeReader    *reader);  void        _dbus_type_reader_read_basic          (DBusTypeReader    *reader,                                                     void              *value);  dbus_bool_t _dbus_type_reader_read_array_of_basic (DBusTypeReader    *reader, @@ -90,23 +126,27 @@ void        _dbus_type_reader_recurse             (DBusTypeReader    *reader,                                                     DBusTypeReader    *subreader);  dbus_bool_t _dbus_type_reader_next                (DBusTypeReader    *reader); -void        _dbus_type_writer_init        (DBusTypeWriter *writer, -                                           int             byte_order, -                                           DBusString     *type_str, -                                           int             type_pos, -                                           DBusString     *value_str, -                                           int             value_pos); -dbus_bool_t _dbus_type_writer_write_basic (DBusTypeWriter *writer, -                                           int             type, -                                           const void     *value); -dbus_bool_t _dbus_type_writer_write_array (DBusTypeWriter *writer, -                                           int             type, -                                           const void     *array, -                                           int             array_len); -dbus_bool_t _dbus_type_writer_recurse     (DBusTypeWriter *writer, -                                           int             container_type, -                                           DBusTypeWriter *sub); -dbus_bool_t _dbus_type_writer_unrecurse   (DBusTypeWriter *writer, -                                           DBusTypeWriter *sub); +void        _dbus_type_writer_init          (DBusTypeWriter *writer, +                                             int             byte_order, +                                             DBusString     *type_str, +                                             int             type_pos, +                                             DBusString     *value_str, +                                             int             value_pos); +dbus_bool_t _dbus_type_writer_write_basic   (DBusTypeWriter *writer, +                                             int             type, +                                             const void     *value); +dbus_bool_t _dbus_type_writer_write_array   (DBusTypeWriter *writer, +                                             int             type, +                                             const void     *array, +                                             int             array_len); +dbus_bool_t _dbus_type_writer_recurse       (DBusTypeWriter *writer, +                                             int             container_type, +                                             DBusTypeWriter *sub); +dbus_bool_t _dbus_type_writer_recurse_array (DBusTypeWriter *writer, +                                             const char     *element_type, +                                             DBusTypeWriter *sub); +dbus_bool_t _dbus_type_writer_unrecurse     (DBusTypeWriter *writer, +                                             DBusTypeWriter *sub); +  #endif /* DBUS_MARSHAL_RECURSIVE_H */ diff --git a/dbus/dbus-protocol-new.h b/dbus/dbus-protocol-new.h index 9d8c4b6f..93cc5668 100644 --- a/dbus/dbus-protocol-new.h +++ b/dbus/dbus-protocol-new.h @@ -42,36 +42,52 @@ extern "C" {  /* Never a legitimate type */  #define DBUS_TYPE_INVALID       ((int) '\0') +#define DBUS_TYPE_INVALID_AS_STRING        "\0"  /* Primitive types */  #define DBUS_TYPE_BYTE          ((int) 'y') +#define DBUS_TYPE_BYTE_AS_STRING           "y"  #define DBUS_TYPE_BOOLEAN       ((int) 'b') +#define DBUS_TYPE_BOOLEAN_AS_STRING        "b"  #define DBUS_TYPE_INT32         ((int) 'i') +#define DBUS_TYPE_INT32_AS_STRING          "i"  #define DBUS_TYPE_UINT32        ((int) 'u') +#define DBUS_TYPE_UINT32_AS_STRING         "u"  #define DBUS_TYPE_INT64         ((int) 'x') +#define DBUS_TYPE_INT64_AS_STRING          "x"  #define DBUS_TYPE_UINT64        ((int) 't') +#define DBUS_TYPE_UINT64_AS_STRING         "t"  #define DBUS_TYPE_DOUBLE        ((int) 'd') +#define DBUS_TYPE_DOUBLE_AS_STRING         "d"  #define DBUS_TYPE_STRING        ((int) 's') +#define DBUS_TYPE_STRING_AS_STRING         "s"  #define DBUS_TYPE_OBJECT_PATH   ((int) 'o') +#define DBUS_TYPE_OBJECT_PATH_AS_STRING    "o"  /* Compound types */  #define DBUS_TYPE_ARRAY         ((int) 'a') +#define DBUS_TYPE_ARRAY_AS_STRING          "a"  #define DBUS_TYPE_DICT          ((int) 'm') /* not parameterized; always map<string,variant> */ +#define DBUS_TYPE_DICT_AS_STRING           "m"  #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   */  #define DBUS_TYPE_STRUCT        ((int) 'r') +#define DBUS_TYPE_STRUCT_AS_STRING         "r"  /* Does not count INVALID */  #define DBUS_NUMBER_OF_TYPES    (13)  /* 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     ")"  /* Max length in bytes of a service or interface or member name */  #define DBUS_MAXIMUM_NAME_LENGTH 256  | 
