diff options
| -rw-r--r-- | ChangeLog | 16 | ||||
| -rw-r--r-- | glib/dbus-binding-tool-glib.c | 26 | ||||
| -rw-r--r-- | glib/dbus-gmain.c | 4 | ||||
| -rw-r--r-- | glib/dbus-gsignature.c | 25 | ||||
| -rw-r--r-- | glib/dbus-gtype-specialized.c | 296 | ||||
| -rw-r--r-- | glib/dbus-gtype-specialized.h | 43 | ||||
| -rw-r--r-- | glib/dbus-gvalue-utils.c | 184 | ||||
| -rw-r--r-- | glib/dbus-gvalue-utils.h | 2 | ||||
| -rw-r--r-- | glib/dbus-gvalue.c | 148 | 
9 files changed, 711 insertions, 33 deletions
@@ -1,3 +1,19 @@ +2006-02-13  Robert McQueen  <robot101@debian.org> + +	* glib/dbus-binding-tool-glib.c, glib/dbus-gmain.c, +	glib/dbus-gsignature.c, glib/dbus-gtype-specialized.c, +	glib/dbus-gtype-specialized.h, glib/dbus-gvalue-utils.c, +	glib/dbus-gvalue-utils.h, glib/dbus-gvalue.c: +	Patch from Rob Taylor <rob.taylor@collabora.co.uk> to add a big +	missing piece of the glib bindings jigsaw puzzle. This modifies +	the existing specialised types to have N type parameters (rather +	than the current 1 or 2 for arrays and dictionaries respectively). +	You can then use this to get a glib type to represent any arbitrary +	D-Bus struct type using dbus_g_type_get_struct. The only +	implementation of these types is with GValueArrays as before, +	but it's now possible to store these in arrays, emit them in +	signals, etc. +  2006-02-10  John (J5) Palmieri  <johnp@redhat.com>  	* dbus/dbus-signature.c (dbus_signature_iter_recurse): Correctly diff --git a/glib/dbus-binding-tool-glib.c b/glib/dbus-binding-tool-glib.c index 21e02744..1386e3f1 100644 --- a/glib/dbus-binding-tool-glib.c +++ b/glib/dbus-binding-tool-glib.c @@ -98,6 +98,10 @@ static const char *  dbus_g_type_get_c_name (GType gtype)  {    GType subtype; +  if (dbus_g_type_is_struct (gtype)) +    { +      return "GValueArray"; +    }    if (dbus_g_type_is_collection (gtype))      {        subtype = dbus_g_type_get_collection_specialization(gtype); @@ -1050,6 +1054,28 @@ dbus_g_type_get_lookup_function (GType gtype)        g_free (value_lookup);        return type_lookup;      } +  else if (dbus_g_type_is_struct (gtype)) +    { +      GType value_gtype; +      GString *string; +      char *value_lookup = NULL; +      guint size, i; + +      string = g_string_new ("dbus_g_type_get_struct (\"GValueArray\""); + +      size = dbus_g_type_get_struct_size (gtype); +      for (i=0; i < size; i++) +        { +          value_gtype = dbus_g_type_get_struct_member_type(gtype, i); +          value_lookup = dbus_g_type_get_lookup_function (value_gtype); +          g_assert (value_lookup); +          g_string_append_printf (string, ", %s", value_lookup); +          g_free (value_lookup); +        } +      g_string_append (string, ", G_TYPE_INVALID)"); +      return g_string_free (string, FALSE); +    } +    MAP_KNOWN(G_TYPE_VALUE);    MAP_KNOWN(G_TYPE_STRV);    MAP_KNOWN(G_TYPE_VALUE_ARRAY); diff --git a/glib/dbus-gmain.c b/glib/dbus-gmain.c index 993bcf37..267f0bfa 100644 --- a/glib/dbus-gmain.c +++ b/glib/dbus-gmain.c @@ -754,14 +754,14 @@ _dbus_gmain_test (const char *test_data_dir)    rectype = dbus_g_type_get_collection ("GArray", G_TYPE_UINT);    g_assert (rectype != G_TYPE_INVALID); -  g_assert (!strcmp (g_type_name (rectype), "GArray+guint")); +  g_assert (!strcmp (g_type_name (rectype), "GArray_guint_"));    type = _dbus_gtype_from_signature ("au", TRUE);    g_assert (type == rectype);    rectype = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING);    g_assert (rectype != G_TYPE_INVALID); -  g_assert (!strcmp (g_type_name (rectype), "GHashTable+gchararray+gchararray")); +  g_assert (!strcmp (g_type_name (rectype), "GHashTable_gchararray+gchararray_"));    type = _dbus_gtype_from_signature ("a{ss}", TRUE);    g_assert (type == rectype); diff --git a/glib/dbus-gsignature.c b/glib/dbus-gsignature.c index a0370b0e..5df959db 100644 --- a/glib/dbus-gsignature.c +++ b/glib/dbus-gsignature.c @@ -117,6 +117,25 @@ signature_iter_to_g_type_array (DBusSignatureIter *iter, gboolean is_client)    return G_TYPE_INVALID;   } +static GType +signature_iter_to_g_type_struct (DBusSignatureIter *iter, gboolean is_client) +{ +  GArray *types; +  GType ret; +  types = g_array_new (FALSE, FALSE, sizeof (GType)); +  do +    { +      GType curtype; +      curtype = _dbus_gtype_from_signature_iter (iter, is_client); +      g_array_append_val (types, curtype); +    } +  while (dbus_signature_iter_next (iter)); + +  ret = dbus_g_type_get_structv ("GValueArray", types->len, (GType*) types->data); +  g_array_free (types, TRUE); +  return ret; +} +  GType  _dbus_gtype_from_signature_iter (DBusSignatureIter *iter, gboolean is_client)  { @@ -136,8 +155,6 @@ _dbus_gtype_from_signature_iter (DBusSignatureIter *iter, gboolean is_client)        if (current_type == DBUS_TYPE_VARIANT)  	return G_TYPE_VALUE; -      if (current_type == DBUS_TYPE_STRUCT) -	return G_TYPE_VALUE_ARRAY;        dbus_signature_iter_recurse (iter, &subiter); @@ -149,6 +166,10 @@ _dbus_gtype_from_signature_iter (DBusSignatureIter *iter, gboolean is_client)  	  else   	    return signature_iter_to_g_type_array (&subiter, is_client);  	} +      else if (current_type == DBUS_TYPE_STRUCT) +        { +          return signature_iter_to_g_type_struct (&subiter, is_client); +        }        else  	{  	  g_assert_not_reached (); diff --git a/glib/dbus-gtype-specialized.c b/glib/dbus-gtype-specialized.c index ad93a8c5..338e49d0 100644 --- a/glib/dbus-gtype-specialized.c +++ b/glib/dbus-gtype-specialized.c @@ -28,7 +28,8 @@  typedef enum {    DBUS_G_SPECTYPE_COLLECTION, -  DBUS_G_SPECTYPE_MAP +  DBUS_G_SPECTYPE_MAP, +  DBUS_G_SPECTYPE_STRUCT  } DBusGTypeSpecializedType;  typedef struct { @@ -37,7 +38,8 @@ typedef struct {  } DBusGTypeSpecializedContainer;  typedef struct { -  GType types[6]; +  guint num_types; +  GType *types;    const DBusGTypeSpecializedContainer     *klass;  } DBusGTypeSpecializedData; @@ -71,6 +73,7 @@ lookup_specialization_data (GType type)    return g_type_get_qdata (type, specialized_type_data_quark ());  } +  /* Copied from gboxed.c */  static void  proxy_value_init (GValue *value) @@ -151,7 +154,9 @@ proxy_collect_value (GValue      *value,  	  value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;  	}        else -	value->data[0].v_pointer = data->klass->vtable->copy_func (type, collect_values[0].v_pointer); +        { +	  value->data[0].v_pointer = data->klass->vtable->copy_func (type, collect_values[0].v_pointer); +        }      }    return NULL; @@ -188,18 +193,21 @@ proxy_lcopy_value (const GValue *value,  }  static char * -build_specialization_name (const char *prefix, GType first_type, GType second_type) +build_specialization_name (const char *prefix, guint num_types, GType *types)  {    GString *fullname; +  guint i;    fullname = g_string_new (prefix); -  g_string_append_c (fullname, '+'); -  g_string_append (fullname, g_type_name (first_type)); -  if (second_type != G_TYPE_INVALID) + +  g_string_append_c (fullname, '_'); +  for (i=0; i < num_types; i++)      { -      g_string_append_c (fullname, '+'); -      g_string_append (fullname, g_type_name (second_type)); +      if (i!=0) +        g_string_append_c (fullname, '+'); +      g_string_append (fullname, g_type_name (types[i]));      } +  g_string_append_c (fullname, '_');    return g_string_free (fullname, FALSE);  } @@ -235,6 +243,16 @@ dbus_g_type_register_map (const char                            *name,    register_container (name, DBUS_G_SPECTYPE_MAP, (const DBusGTypeSpecializedVtable*) vtable);  } +void +dbus_g_type_register_struct (const char                             *name, +			     const DBusGTypeSpecializedStructVtable *vtable, +			     guint                                   flags) +{ +  g_return_if_fail (specialized_types_is_initialized ()); +  register_container (name, DBUS_G_SPECTYPE_STRUCT, (const DBusGTypeSpecializedVtable*) vtable); +} + +  const DBusGTypeSpecializedMapVtable* dbus_g_type_map_peek_vtable (GType map_type)  {    DBusGTypeSpecializedData *data; @@ -257,12 +275,22 @@ const DBusGTypeSpecializedCollectionVtable* dbus_g_type_collection_peek_vtable (    return (DBusGTypeSpecializedCollectionVtable *)(data->klass->vtable);  } +const DBusGTypeSpecializedStructVtable* dbus_g_type_struct_peek_vtable (GType struct_type) +{ +  DBusGTypeSpecializedData *data; +  g_return_val_if_fail (dbus_g_type_is_struct (struct_type), NULL); + +  data = lookup_specialization_data (struct_type); +  g_assert (data != NULL); + +  return (DBusGTypeSpecializedStructVtable *)(data->klass->vtable); +}  static GType  register_specialized_instance (const DBusGTypeSpecializedContainer   *klass,  			       char                                  *name, -			       GType                                  first_type, -			       GType                                  second_type) +			       guint                                  num_types, +			       GType                                 *types)  {    GType ret; @@ -297,8 +325,8 @@ register_specialized_instance (const DBusGTypeSpecializedContainer   *klass,      {        DBusGTypeSpecializedData *data;        data = g_new0 (DBusGTypeSpecializedData, 1); -      data->types[0] = first_type; -      data->types[1] = second_type; +      data->num_types = num_types; +      data->types = g_memdup (types, sizeof (GType) * num_types);        data->klass = klass;        g_type_set_qdata (ret, specialized_type_data_quark (), data);      } @@ -308,8 +336,8 @@ register_specialized_instance (const DBusGTypeSpecializedContainer   *klass,  static GType  lookup_or_register_specialized (const char  *container, -				GType       first_type, -				GType       second_type) +				guint        num_types, +				GType       *types)  {    GType ret;    char *name; @@ -320,14 +348,14 @@ lookup_or_register_specialized (const char  *container,    klass = g_hash_table_lookup (specialized_containers, container);    g_return_val_if_fail (klass != NULL, G_TYPE_INVALID); -  name = build_specialization_name (container, first_type, second_type); +  name = build_specialization_name (container, num_types, types);    ret = g_type_from_name (name);    if (ret == G_TYPE_INVALID)      {        /* Take ownership of name */        ret = register_specialized_instance (klass, name, -					   first_type, -					   second_type); +					   num_types, +					   types);      }    else      g_free (name); @@ -338,7 +366,7 @@ GType  dbus_g_type_get_collection (const char *container,  			    GType       specialization)  { -  return lookup_or_register_specialized (container, specialization, G_TYPE_INVALID); +  return lookup_or_register_specialized (container, 1, &specialization);  }  GType @@ -346,9 +374,42 @@ dbus_g_type_get_map (const char   *container,  		     GType         key_specialization,  		     GType         value_specialization)  { -  return lookup_or_register_specialized (container, key_specialization, value_specialization); +  GType types[2] = {key_specialization, value_specialization}; +  return lookup_or_register_specialized (container, 2, types); +} + +GType +dbus_g_type_get_structv (const char   *container, +                        guint         num_items, +                        GType        *types) +{ +  return lookup_or_register_specialized (container, num_items, types);  } +GType +dbus_g_type_get_struct (const char *container, +                        GType first_type, +                        ...) +{ +  GArray *types; +  GType curtype; +  va_list args; +  va_start (args, first_type); + +  types = g_array_new (FALSE, FALSE, sizeof (GType)); +  curtype = first_type; +  while (curtype != G_TYPE_INVALID) +    { +      g_array_append_val (types, curtype); +      curtype = va_arg (args, GType); +    } +  va_end (args); +  return lookup_or_register_specialized (container, types->len, (GType*)types->data); + +} + + +  gboolean  dbus_g_type_is_collection (GType gtype)  { @@ -369,13 +430,27 @@ dbus_g_type_is_map (GType gtype)    return data->klass->type == DBUS_G_SPECTYPE_MAP;  } +gboolean +dbus_g_type_is_struct (GType gtype) +{ +  DBusGTypeSpecializedData *data; +  data = lookup_specialization_data (gtype); +  if (data == NULL) +    return FALSE; +  return data->klass->type == DBUS_G_SPECTYPE_STRUCT; +} + +  static GType  get_specialization_index (GType gtype, guint i)  {    DBusGTypeSpecializedData *data;    data = lookup_specialization_data (gtype); -  return data->types[i]; +  if (i < data->num_types) +    return data->types[i]; +  else +    return G_TYPE_INVALID;  }  GType @@ -399,6 +474,25 @@ dbus_g_type_get_map_value_specialization (GType gtype)    return get_specialization_index (gtype, 1);  } +GType +dbus_g_type_get_struct_member_type (GType gtype, guint index) +{ +  g_return_val_if_fail (dbus_g_type_is_struct (gtype), G_TYPE_INVALID); +  return get_specialization_index (gtype, index); +} + +guint +dbus_g_type_get_struct_size (GType gtype) +{ +  DBusGTypeSpecializedData *data; +  g_return_val_if_fail (dbus_g_type_is_struct (gtype), G_TYPE_INVALID); + +  data = lookup_specialization_data (gtype); +  return data->num_types; +} + + +  gpointer  dbus_g_type_specialized_construct (GType type)  { @@ -469,7 +563,8 @@ dbus_g_type_specialized_init_append (GValue *value, DBusGTypeSpecializedAppendCo    gtype = G_VALUE_TYPE (value);    specdata = lookup_specialization_data (gtype);    g_return_if_fail (specdata != NULL); -   +  g_return_if_fail (specdata->num_types != 0); +    realctx->val = value;    realctx->specialization_type = specdata->types[0];    realctx->specdata = specdata; @@ -519,3 +614,160 @@ dbus_g_type_map_value_iterate (const GValue                           *value,  								     g_value_get_boxed (value),  								     iterator, user_data);  } + +gboolean +dbus_g_type_struct_get_member (const GValue *value, +			       guint         index, +			       GValue       *dest) +{ +  DBusGTypeSpecializedData *data; +  GType gtype; + +  g_return_val_if_fail (specialized_types_is_initialized (), FALSE); +  g_return_val_if_fail (G_VALUE_HOLDS_BOXED (value), FALSE); + +  gtype = G_VALUE_TYPE (value); +  data = lookup_specialization_data (gtype); +  g_return_val_if_fail (data != NULL, FALSE); + +  return ((DBusGTypeSpecializedStructVtable *) (data->klass->vtable))->get_member(gtype, +											   g_value_get_boxed (value), +											   index, dest); +} + +gboolean +dbus_g_type_struct_set_member (GValue       *value, +			       guint         index, +			       const GValue *src) +{ +  DBusGTypeSpecializedData *data; +  GType gtype; + +  g_return_val_if_fail (specialized_types_is_initialized (), FALSE); +  g_return_val_if_fail (G_VALUE_HOLDS_BOXED (value), FALSE); + +  gtype = G_VALUE_TYPE (value); +  data = lookup_specialization_data (gtype); +  g_return_val_if_fail (data != NULL, FALSE); + +  return ((DBusGTypeSpecializedStructVtable *) (data->klass->vtable))->set_member(gtype, +											   g_value_get_boxed (value), +											   index, src); +} + +/** + * dbus_g_type_struct_get: + * @value: a GValue containing a DBusGTypeStruct type + * @member: struct member to get + * @...: location in which to return the value of this member, + *       followed optionally by more member/return locations pairs, followed by + *       by G_MAXUINT + * + * Collects the selected values of this struct into the return locations + * provided. + * + * Returns: FALSE on failure + */ + +gboolean +dbus_g_type_struct_get                   (const GValue *value, +                                          guint first_member, +                                          ...) +{ +  va_list var_args; +  GType type; +  guint size,i; +  gchar *error; +  GValue val = {0,}; + +  g_return_val_if_fail (dbus_g_type_is_struct (G_VALUE_TYPE (value)), FALSE); + +  va_start (var_args, first_member); +  size = dbus_g_type_get_struct_size (G_VALUE_TYPE (value)); +  i = first_member; +  while (i != G_MAXUINT) +    { +      if (i >= size) +        goto error; + +      type = dbus_g_type_get_struct_member_type (G_VALUE_TYPE (value),i); + +      g_value_init (&val, type); +      dbus_g_type_struct_get_member (value, i, &val); + +      G_VALUE_LCOPY (&val, var_args, 0, &error); +      if (error) +        { +          g_warning ("%s, %s", G_STRFUNC, error); +          g_free (error); +          g_value_unset (&val); +          goto error; +        } +      g_value_unset (&val); +      i = va_arg (var_args, guint); +    } +  va_end (var_args); +  return TRUE; +error: +  va_end (var_args); +  return FALSE; +} + +/** + * dbus_g_type_struct_set: + * @value: a GValue containing a DBusGTypeStruct type + * @member: struct member to set + * @...: value for the first member, followed optionally by + *       more member/value pairs, followed by G_MAXUINT + * + * Sets the selected members of the struct in @value. + * + * Returns: FALSE on failure + */ + +gboolean +dbus_g_type_struct_set                   (GValue *value, +                                          guint first_member, +                                          ...) +{ +  va_list var_args; +  GType type; +  guint size,i; +  gchar *error; +  GValue val = {0,}; + +  g_return_val_if_fail (dbus_g_type_is_struct (G_VALUE_TYPE (value)), FALSE); + +  va_start (var_args, first_member); +  size = dbus_g_type_get_struct_size (G_VALUE_TYPE (value)); +  i = first_member; +  while (i != G_MAXUINT) +    { +      if (i >= size) +        goto error; + +      type = dbus_g_type_get_struct_member_type (G_VALUE_TYPE (value),i); + +      g_value_init (&val, type); + +      G_VALUE_COLLECT (&val, var_args, 0, &error); +      if (error) +        { +          g_warning ("%s, %s", G_STRFUNC, error); +          g_free (error); +          g_value_unset (&val); +          goto error; +        } + +      dbus_g_type_struct_set_member (value, i, &val); + +      g_value_unset (&val); +      i = va_arg (var_args, guint); +    } +  va_end (var_args); +  return TRUE; +error: +  va_end (var_args); +  return FALSE; +} + diff --git a/glib/dbus-gtype-specialized.h b/glib/dbus-gtype-specialized.h index 505c95bc..1d260092 100644 --- a/glib/dbus-gtype-specialized.h +++ b/glib/dbus-gtype-specialized.h @@ -34,11 +34,21 @@ GType          dbus_g_type_get_collection                   (const char *contain  GType          dbus_g_type_get_map                          (const char *container,  							     GType       key_specialization,  							     GType       value_specialization); +GType          dbus_g_type_get_structv                      (const char *container, +							     guint       num_items, +							     GType      *types); +GType          dbus_g_type_get_struct                       (const char *container, +                                                             GType       first_type, +                                                             ...);  gboolean       dbus_g_type_is_collection                    (GType       gtype);  gboolean       dbus_g_type_is_map                           (GType       gtype); +gboolean       dbus_g_type_is_struct                        (GType       gtype);  GType          dbus_g_type_get_collection_specialization    (GType       gtype);  GType          dbus_g_type_get_map_key_specialization       (GType       gtype);  GType          dbus_g_type_get_map_value_specialization     (GType       gtype); +GType          dbus_g_type_get_struct_member_type           (GType       gtype, +                                                             guint       index); +guint          dbus_g_type_get_struct_size                  (GType       gtype);  typedef void   (*DBusGTypeSpecializedCollectionIterator)    (const GValue *val,  							     gpointer      user_data); @@ -81,6 +91,21 @@ void           dbus_g_type_map_value_iterate                (const GValue  							     DBusGTypeSpecializedMapIterator         iterator,  							     gpointer                                user_data); +gboolean       dbus_g_type_struct_get_member            (const GValue *value, +                                                         guint index, +                                                         GValue *dest); +gboolean       dbus_g_type_struct_set_member            (GValue *value, +                                                         guint index, +                                                         const GValue *src); + +gboolean       dbus_g_type_struct_get                   (const GValue *value, +                                                         guint member, +                                                         ...); + +gboolean       dbus_g_type_struct_set                   (GValue *value, +                                                         guint member, +                                                         ...); +  typedef gpointer (*DBusGTypeSpecializedConstructor)     (GType type);  typedef void     (*DBusGTypeSpecializedFreeFunc)        (GType type, gpointer val);  typedef gpointer (*DBusGTypeSpecializedCopyFunc)        (GType type, gpointer src); @@ -116,6 +141,15 @@ typedef struct {    DBusGTypeSpecializedMapAppendFunc                 append_func;  } DBusGTypeSpecializedMapVtable; +typedef gboolean (*DBusGTypeSpecializedStructGetMember) (GType type, gpointer instance, guint member, GValue *ret_value); +typedef gboolean (*DBusGTypeSpecializedStructSetMember) (GType type, gpointer instance, guint member, const GValue *new_value); + +typedef struct { +  DBusGTypeSpecializedVtable                        base_vtable; +  DBusGTypeSpecializedStructGetMember               get_member; +  DBusGTypeSpecializedStructSetMember               set_member; +} DBusGTypeSpecializedStructVtable; +  void           dbus_g_type_specialized_init           (void);  void           dbus_g_type_register_collection        (const char                                   *name, @@ -128,6 +162,15 @@ void           dbus_g_type_register_map               (const char  const DBusGTypeSpecializedMapVtable* dbus_g_type_map_peek_vtable (GType map_type);  const DBusGTypeSpecializedCollectionVtable* dbus_g_type_collection_peek_vtable (GType collection_type); +void           dbus_g_type_register_struct             (const char                                   *name, +						       const DBusGTypeSpecializedStructVtable        *vtable, +						       guint                                          flags); + +const DBusGTypeSpecializedMapVtable* dbus_g_type_map_peek_vtable (GType map_type); +const DBusGTypeSpecializedCollectionVtable* dbus_g_type_collection_peek_vtable (GType collection_type); + +const DBusGTypeSpecializedStructVtable* dbus_g_type_struct_peek_vtable (GType struct_type); +  G_END_DECLS  #endif diff --git a/glib/dbus-gvalue-utils.c b/glib/dbus-gvalue-utils.c index 04c0c3e8..f64a921f 100644 --- a/glib/dbus-gvalue-utils.c +++ b/glib/dbus-gvalue-utils.c @@ -334,6 +334,16 @@ hash_free_from_gtype (GType gtype, GDestroyNotify *func)                return TRUE;              }          } +      else if (dbus_g_type_is_struct (gtype)) +        { +          const DBusGTypeSpecializedStructVtable *vtable; +          vtable = dbus_g_type_struct_peek_vtable (gtype); +          if (vtable->base_vtable.simple_free_func) +            { +              *func = vtable->base_vtable.simple_free_func; +              return TRUE; +            } +        }        return FALSE;      }  } @@ -612,6 +622,67 @@ hashtable_simple_free (gpointer val)  }  static gpointer +valuearray_constructor (GType type) +{ +  GValueArray *ret; +  guint size = dbus_g_type_get_struct_size (type); +  guint i; +  ret = g_value_array_new (size); +  for (i=0; i < size; i++) +    { +      GValue val = {0,}; +      g_value_init (&val, dbus_g_type_get_struct_member_type (type, i)); +      g_value_array_append(ret, &val); +    } +  return (gpointer)ret; +} + +static gpointer +valuearray_copy (GType type, gpointer src) +{ +  return g_value_array_copy ((GValueArray*) src); +} + +static void +valuearray_simple_free (gpointer val) +{ +  g_value_array_free (val); +} + +static gboolean +valuearray_get_member (GType type, gpointer instance, +                       guint member, GValue *ret) +{ +  GValueArray *va = (GValueArray*) instance; +  const GValue *val; +  if (member < dbus_g_type_get_struct_size (type)) +    { +      val = g_value_array_get_nth (va, member); +      g_value_copy (val, ret); +      return TRUE; +    } +  else +    return FALSE; +} + +static gboolean +valuearray_set_member (GType type, gpointer instance, +                       guint member, const GValue *member_type) +{ +  GValueArray *va = (GValueArray*) instance; +  GValue *vp; +  if (member < dbus_g_type_get_struct_size (type)) +    { +      vp = g_value_array_get_nth (va, member); +      g_value_copy (member_type, vp); +      return TRUE; +    } +  else +    return FALSE; +} + + +static gpointer  array_constructor (GType type)  {    GArray *array; @@ -945,10 +1016,24 @@ _dbus_g_type_specialized_builtins_init (void)      hashtable_append    }; +  static const DBusGTypeSpecializedStructVtable valuearray_vtable = { +    { +      valuearray_constructor, +      NULL, +      valuearray_copy, +      valuearray_simple_free, +      NULL, +      NULL +    }, +    valuearray_get_member, +    valuearray_set_member +  }; +    dbus_g_type_register_collection ("GSList", &slist_vtable, 0);    dbus_g_type_register_collection ("GArray", &array_vtable, 0);    dbus_g_type_register_collection ("GPtrArray", &ptrarray_vtable, 0);    dbus_g_type_register_map ("GHashTable", &hashtable_vtable, 0); +  dbus_g_type_register_struct ("GValueArray", &valuearray_vtable, 0);  }  #ifdef DBUS_BUILD_TESTS @@ -1160,6 +1245,105 @@ _dbus_gvalue_utils_test (const char *datadir)      g_value_unset (&val);    } +  type = dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_UINT, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); +  g_assert (dbus_g_type_is_struct (type)); +  g_assert (dbus_g_type_get_struct_size (type) == 3); +  g_assert (dbus_g_type_get_struct_member_type (type, 0) == G_TYPE_STRING); +  g_assert (dbus_g_type_get_struct_member_type (type, 1) == G_TYPE_UINT); +  g_assert (dbus_g_type_get_struct_member_type (type, 2) == DBUS_TYPE_G_OBJECT_PATH); +  { +    GValueArray *instance; +    GValue val = {0, }; +    GValue memval = {0, }; + +    instance = dbus_g_type_specialized_construct (type); + +    g_assert (instance->n_values == 3); + +    g_value_init (&val, type); +    g_value_set_boxed_take_ownership (&val, instance); + +    g_value_init (&memval, G_TYPE_STRING); +    g_value_set_static_string (&memval, "foo"); +    dbus_g_type_struct_set_member (&val, 0, &memval); +    g_value_unset (&memval); + +    g_value_init (&memval, G_TYPE_UINT); +    g_value_set_uint (&memval, 42); +    dbus_g_type_struct_set_member (&val, 1, &memval); +    g_value_unset (&memval); + +    g_value_init (&memval, DBUS_TYPE_G_OBJECT_PATH); +    g_value_set_static_boxed (&memval, "/bar/moo/foo/baz"); +    dbus_g_type_struct_set_member (&val, 2, &memval); +    g_value_unset (&memval); + +    g_assert (instance->n_values == 3); + +    g_value_init (&memval, G_TYPE_STRING); +    dbus_g_type_struct_get_member (&val, 0, &memval); +    g_assert (0 == strcmp (g_value_get_string (&memval), "foo")); +    g_value_unset (&memval); + +    g_value_init (&memval, G_TYPE_UINT); +    dbus_g_type_struct_get_member (&val, 1, &memval); +    g_assert (g_value_get_uint (&memval) == 42); +    g_value_unset (&memval); + +    g_value_init (&memval, DBUS_TYPE_G_OBJECT_PATH); +    dbus_g_type_struct_get_member (&val, 2, &memval); +    g_assert (0 == strcmp ((gchar*) g_value_get_boxed (&memval), +                           "/bar/moo/foo/baz")); +    g_value_unset (&memval); + +    g_value_unset (&val); +  } + +  type = dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_UINT, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); +  g_assert (dbus_g_type_is_struct (type)); +  g_assert (dbus_g_type_get_struct_size (type) == 3); +  g_assert (dbus_g_type_get_struct_member_type (type, 0) == G_TYPE_STRING); +  g_assert (dbus_g_type_get_struct_member_type (type, 1) == G_TYPE_UINT); +  g_assert (dbus_g_type_get_struct_member_type (type, 2) == DBUS_TYPE_G_OBJECT_PATH); +  { +    GValueArray *instance; +    GValue val = {0, }; + +    instance = dbus_g_type_specialized_construct (type); + +    g_assert (instance->n_values == 3); + +    g_value_init (&val, type); +    g_value_set_boxed_take_ownership (&val, instance); + +    dbus_g_type_struct_set (&val, +                            0,"foo", +                            1, 42, +                            2, "/bar/moo/foo/baz", +                            G_MAXUINT); + +    g_assert (instance->n_values == 3); + +    { +      gchar *string; +      guint intval; +      gchar *path; + +      dbus_g_type_struct_get (&val, +                              0, &string, +                              1, &intval, +                              2, &path, +                              G_MAXUINT); + +      g_assert (0 == strcmp (string, "foo")); +      g_assert (intval == 42); +      g_assert (0 == strcmp (path, "/bar/moo/foo/baz")); +    } + +    g_value_unset (&val); +  } + +    return TRUE;  } diff --git a/glib/dbus-gvalue-utils.h b/glib/dbus-gvalue-utils.h index 139f4a31..cba3b61a 100644 --- a/glib/dbus-gvalue-utils.h +++ b/glib/dbus-gvalue-utils.h @@ -29,7 +29,7 @@  G_BEGIN_DECLS -void          _dbus_g_type_specialized_builtins_init (void); +void           _dbus_g_type_specialized_builtins_init (void);  gboolean       _dbus_g_type_is_fixed                  (GType gtype);   guint          _dbus_g_type_fixed_get_size            (GType gtype);  diff --git a/glib/dbus-gvalue.c b/glib/dbus-gvalue.c index e332e71a..3e8cf1e7 100644 --- a/glib/dbus-gvalue.c +++ b/glib/dbus-gvalue.c @@ -107,6 +107,13 @@ static gboolean demarshal_collection_array      (DBusGValueMarshalCtx      *cont  						 DBusMessageIter           *iter,  						 GValue                    *value,  						 GError                   **error); +static gboolean marshal_struct                  (DBusMessageIter           *iter, +						 const GValue              *value); +static gboolean demarshal_struct                (DBusGValueMarshalCtx      *context, +						 DBusMessageIter           *iter, +						 GValue                    *value, +						 GError                   **error); +  typedef gboolean (*DBusGValueMarshalFunc)       (DBusMessageIter           *iter,  						 const GValue              *value); @@ -346,6 +353,7 @@ dbus_g_object_path_get_g_type (void)    return type_id;  } +  char *  _dbus_gtype_to_signature (GType gtype)  { @@ -377,6 +385,21 @@ _dbus_gtype_to_signature (GType gtype)        g_free (key_subsig);        g_free (val_subsig);      } +  else if (dbus_g_type_is_struct (gtype)) +    { +      guint i, size; +      GString *sig; +      size = dbus_g_type_get_struct_size (gtype); +      sig = g_string_sized_new (size+2); /*some sensible starting size*/ +      g_string_assign (sig, DBUS_STRUCT_BEGIN_CHAR_AS_STRING); +      for (i=0; i < size; i++) +        { +          g_string_append (sig, _dbus_gtype_to_signature ( +              dbus_g_type_get_struct_member_type (gtype, i))); +        } +      g_string_append (sig, DBUS_STRUCT_END_CHAR_AS_STRING); +      ret = g_string_free (sig, FALSE); +    }    else      {        typedata = g_type_get_qdata (gtype, dbus_g_type_metadata_data_quark ()); @@ -384,7 +407,6 @@ _dbus_gtype_to_signature (GType gtype)  	return NULL;        ret = g_strdup (typedata->sig);      } -      return ret;  } @@ -851,6 +873,76 @@ demarshal_map (DBusGValueMarshalCtx    *context,    return TRUE;  } +static gboolean +demarshal_struct (DBusGValueMarshalCtx    *context, +                  DBusMessageIter         *iter, +                  GValue                  *value, +                  GError                 **error) +{ +  int current_type; +  DBusMessageIter subiter; +  guint i, size; +  GValue val = {0,}; +  GType elt_type; + +  current_type = dbus_message_iter_get_arg_type (iter); +  if (current_type != DBUS_TYPE_STRUCT) +    { +      g_set_error (error, +                   DBUS_GERROR, +                   DBUS_GERROR_INVALID_ARGS, +                   _("Expected D-BUS struct, got type code \'%c\'"), (guchar) current_type); +      return FALSE; +    } + +  dbus_message_iter_recurse (iter, &subiter); + +  g_value_set_boxed_take_ownership (value, +    dbus_g_type_specialized_construct (G_VALUE_TYPE (value))); + +  size = dbus_g_type_get_struct_size (G_VALUE_TYPE (value)); + +  for (i=0; i < size; i++) +    { + +      elt_type = dbus_g_type_get_struct_member_type (G_VALUE_TYPE(value), i); +      if (elt_type == G_TYPE_INVALID) +        { +          g_value_unset (value); +          g_set_error (error, +                       DBUS_GERROR, +                       DBUS_GERROR_INVALID_ARGS, +                       _("Couldn't demarshal argument, " +                         "struct type %s has no member %d"), +                       g_type_name (G_VALUE_TYPE(value)), i); +          return FALSE; +        } + +      g_value_init (&val, elt_type); + +      if (!_dbus_gvalue_demarshal (context, &subiter, &val, error)) +        { +          g_value_unset (&val); +          g_value_unset (value); +          return FALSE; +        } +      if (!dbus_g_type_struct_set_member (value, i, &val)) +        { +          g_value_unset (&val); +          g_value_unset (value); +          return FALSE; +        } + +      dbus_message_iter_next (&subiter); +      g_value_unset (&val); +    } + +  g_assert (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_INVALID); + +  return TRUE; +} + +  static DBusGValueDemarshalFunc  get_type_demarshaller (GType type)  { @@ -865,6 +957,8 @@ get_type_demarshaller (GType type)  	return demarshal_collection;        if (dbus_g_type_is_map (type))  	return demarshal_map; +      if (dbus_g_type_is_struct (type)) +        return demarshal_struct;        g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));        return NULL; @@ -1453,6 +1547,48 @@ marshal_map (DBusMessageIter   *iter,  }  static gboolean +marshal_struct (DBusMessageIter   *iter, +                const GValue      *value) +{ +  GType gtype; +  DBusMessageIter subiter; +  gboolean ret; +  guint size, i; +  GValue val = {0,}; + +  gtype = G_VALUE_TYPE (value); + +  ret = FALSE; + +  size = dbus_g_type_get_struct_size (gtype); + +  if (!dbus_message_iter_open_container (iter, +                                         DBUS_TYPE_STRUCT, +                                         NULL, +                                         &subiter)) +    goto oom; + +  for (i = 0; i < size; i++) +    { +      g_value_init (&val, dbus_g_type_get_struct_member_type +          (G_VALUE_TYPE(value), i)); +      if (!dbus_g_type_struct_get_member (value, i, &val)) +        return FALSE; +      if (!_dbus_gvalue_marshal (&subiter, &val)) +        return FALSE; +      g_value_unset(&val); +    } + +  if (!dbus_message_iter_close_container (iter, &subiter)) +    goto oom; + +  return TRUE; + oom: +  g_error ("out of memory"); +  return FALSE; +} + +static gboolean  marshal_variant (DBusMessageIter          *iter,  		 const GValue             *value)  { @@ -1504,6 +1640,8 @@ get_type_marshaller (GType type)  	return marshal_collection;        if (dbus_g_type_is_map (type))  	return marshal_map; +      if (dbus_g_type_is_struct (type)) +	return marshal_struct;        g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));        return NULL; @@ -1697,17 +1835,15 @@ _dbus_gvalue_test (const char *test_data_dir)    assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);    assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING); -  assert_signature_maps_to (DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING, G_TYPE_VALUE_ARRAY); -  assert_signature_maps_to (DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING, G_TYPE_VALUE_ARRAY); -  assert_signature_maps_to (DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_TYPE_UINT32_AS_STRING DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING, G_TYPE_VALUE_ARRAY); -    assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), -				DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING); +			      DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING);    assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),  				DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);    assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),  				DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING); +  assert_bidirectional_mapping (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_STRING, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID), +  				DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING );    return TRUE;  }  | 
