2005-07-11 Colin Walters <walters@verbum.org>
authorColin Walters <walters@verbum.org>
Mon, 11 Jul 2005 16:12:50 +0000 (16:12 +0000)
committerColin Walters <walters@verbum.org>
Mon, 11 Jul 2005 16:12:50 +0000 (16:12 +0000)
* glib/dbus-gvalue.c (struct _DBusGValue): Delete.
(dbus_g_value_types_init): Remove assertion.
(dbus_g_value_get_g_type, dbus_g_value_open)
(dbus_g_value_iterator_get_values, dbus_g_value_get_signature)
(dbus_g_value_copy, dbus_g_value_free): Delete unimplemented
functions related to DBusGValue.  Now we marshal/demarshal
structures as GValueArray.
(dbus_gtype_from_signature_iter): Return G_TYPE_VALUE_ARRAY for
structures.
(signature_iter_to_g_type_array): Don't call
signature_iter_to_g_type_struct.
(signature_iter_to_g_type_struct): Delete.
(dbus_gvalue_to_signature): Delete.
(dbus_gvalue_to_signature): New function with same name as other
one; we can convert structures to signatures.
(demarshal_valuearray): New function.
(get_type_demarshaller): Use it.
(demarshal_recurse): Delete.
(marshal_proxy): New function.
(marshal_map): Warn if we can't determine signature from type.
(marshal_collection_ptrarray): Ditto.
(marshal_collection_array): Ditto.
(get_type_marshaller): Use marshal_valuearray.
(marshal_recurse): Delete.
(_dbus_gvalue_test): Add some tests.

* dbus/dbus-glib.h (struct _DBusGValueIterator):
(dbus_g_value_get_g_type, DBUS_TYPE_G_VALUE)
(dbus_g_value_open, dbus_g_value_iterator_get_value)
(dbus_g_value_iterator_get_values, dbus_g_value_iterator_recurse)
(dbus_g_value_free): Remove prototypes.

* glib/dbus-binding-tool-glib.c (dbus_g_type_get_lookup_function): Handle
G_TYPE_VALUE_ARRAY.

* glib/examples/example-service.c:
* glib/examples/example-client.c: Implement GetTuple.

* test/glib/test-dbus-glib.c:
* test/glib/test-service-glib.c:
* test/glib/test-service-glib.xml: Add structure tests.

ChangeLog
dbus/dbus-glib.h
glib/dbus-binding-tool-glib.c
glib/dbus-gvalue.c
glib/examples/example-client.c
glib/examples/example-service.c
test/glib/test-dbus-glib.c
test/glib/test-service-glib.c
test/glib/test-service-glib.xml

index 53023dd..965c462 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,47 @@
+2005-07-11  Colin Walters  <walters@verbum.org>
+
+       * glib/dbus-gvalue.c (struct _DBusGValue): Delete.
+       (dbus_g_value_types_init): Remove assertion.
+       (dbus_g_value_get_g_type, dbus_g_value_open)
+       (dbus_g_value_iterator_get_values, dbus_g_value_get_signature)
+       (dbus_g_value_copy, dbus_g_value_free): Delete unimplemented
+       functions related to DBusGValue.  Now we marshal/demarshal
+       structures as GValueArray.
+       (dbus_gtype_from_signature_iter): Return G_TYPE_VALUE_ARRAY for
+       structures.
+       (signature_iter_to_g_type_array): Don't call
+       signature_iter_to_g_type_struct.
+       (signature_iter_to_g_type_struct): Delete.
+       (dbus_gvalue_to_signature): Delete.
+       (dbus_gvalue_to_signature): New function with same name as other
+       one; we can convert structures to signatures.
+       (demarshal_valuearray): New function.
+       (get_type_demarshaller): Use it.
+       (demarshal_recurse): Delete.
+       (marshal_proxy): New function.
+       (marshal_map): Warn if we can't determine signature from type.
+       (marshal_collection_ptrarray): Ditto.
+       (marshal_collection_array): Ditto.
+       (get_type_marshaller): Use marshal_valuearray.
+       (marshal_recurse): Delete.
+       (_dbus_gvalue_test): Add some tests.
+
+       * dbus/dbus-glib.h (struct _DBusGValueIterator): 
+       (dbus_g_value_get_g_type, DBUS_TYPE_G_VALUE)
+       (dbus_g_value_open, dbus_g_value_iterator_get_value)
+       (dbus_g_value_iterator_get_values, dbus_g_value_iterator_recurse)
+       (dbus_g_value_free): Remove prototypes.
+
+       * glib/dbus-binding-tool-glib.c (dbus_g_type_get_lookup_function): Handle
+       G_TYPE_VALUE_ARRAY.
+
+       * glib/examples/example-service.c:
+       * glib/examples/example-client.c: Implement GetTuple.
+
+       * test/glib/test-dbus-glib.c:
+       * test/glib/test-service-glib.c:
+       * test/glib/test-service-glib.xml: Add structure tests.
+
 2005-07-10  Colin Walters  <walters@verbum.org>
 
        * doc/TODO: Knock off some GLib items with this patch.
index ad156b8..5b5095d 100644 (file)
@@ -115,34 +115,6 @@ void       dbus_g_connection_register_g_object (DBusGConnection       *connectio
 GObject *  dbus_g_connection_lookup_g_object   (DBusGConnection       *connection,
                                                const char            *at_path);
 
-
-/**
- * Generic recursive value
- */
-
-typedef struct _DBusGValueIterator DBusGValueIterator;
-struct _DBusGValueIterator
-{
-  void *dummy1;         /**< Don't use this */
-  void *dummy2;         /**< Don't use this */
-  guint32 dummy3;     /**< Don't use this */
-  int dummy4;           /**< Don't use this */
-  int dummy5;           /**< Don't use this */
-  int dummy6;           /**< Don't use this */
-  int dummy7;           /**< Don't use this */
-  int dummy8;           /**< Don't use this */
-  int dummy9;           /**< Don't use this */
-  int dummy10;          /**< Don't use this */
-  int dummy11;          /**< Don't use this */
-  int pad1;             /**< Don't use this */
-  int pad2;             /**< Don't use this */
-  void *pad3;           /**< Don't use this */
-  void *pad4;           /**< Don't use this */
-  void *pad5;           /**< Don't use this */
-};
-
-typedef struct _DBusGValue DBusGValue;
-
 #ifdef DBUS_COMPILATION
 #include "glib/dbus-gtype-specialized.h"
 #else
@@ -160,30 +132,9 @@ typedef struct _DBusGValue DBusGValue;
 
 #define DBUS_TYPE_G_STRING_STRING_HASHTABLE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING))
 
-/* Generic recursive value */
-GType        dbus_g_value_get_g_type               (void) G_GNUC_CONST;
-#define DBUS_TYPE_G_VALUE                (dbus_g_value_get_g_type ())
-
 GType        dbus_g_object_path_get_g_type         (void) G_GNUC_CONST;
 #define DBUS_TYPE_G_OBJECT_PATH (dbus_g_object_path_get_g_type ())
 
-void         dbus_g_value_open              (DBusGValue          *value,
-                                            DBusGValueIterator  *iter);
-
-GType        dbus_g_value_iterator_get_value        (DBusGValueIterator   *iter,
-                                                    GValue               *value);
-
-gboolean     dbus_g_value_iterator_get_values       (DBusGValueIterator   *iter,
-                                                    GError              **error,
-                                                    GValue               *first_val,
-                                                    ...);
-
-void         dbus_g_value_iterator_recurse          (DBusGValueIterator   *iter,
-                                                    DBusGValueIterator   *sub);
-
-void         dbus_g_value_free                      (DBusGValue          *value);
-
-
 void         dbus_g_object_register_marshaller      (GClosureMarshal  marshaller,
                                                     GType            rettype,
                                                     ...);
index 43b23c6..39c180f 100644 (file)
@@ -1032,6 +1032,7 @@ dbus_g_type_get_lookup_function (GType gtype)
     }
   MAP_KNOWN(G_TYPE_VALUE);
   MAP_KNOWN(G_TYPE_STRV);
+  MAP_KNOWN(G_TYPE_VALUE_ARRAY);
   MAP_KNOWN(DBUS_TYPE_G_PROXY);
   MAP_KNOWN(DBUS_TYPE_G_OBJECT_PATH);
   return NULL;
index 8839773..e5f019f 100644 (file)
@@ -37,29 +37,8 @@ static gboolean demarshal_static_variant (DBusGValueMarshalCtx    *context,
                                          DBusMessageIter         *iter,
                                          GValue                  *value,
                                          GError                 **error);
-static gpointer dbus_g_value_copy (gpointer value);
 
 
-struct _DBusGValue
-{
-  enum {
-    DBUS_G_VALUE_TYPE_TOPLEVEL,
-    DBUS_G_VALUE_TYPE_ITERATOR
-  } type;
-  union {
-    struct {
-      DBusGConnection        *connection;
-      DBusGProxy             *proxy;
-      DBusMessage            *message;
-      char                   *signature;
-    } toplevel;
-    struct {
-      DBusGValue             *toplevel;
-      DBusMessageIter         iterator;
-    } recurse;
-  } value;
-};
-
 static gboolean marshal_basic                   (DBusMessageIter           *iter,
                                                 const GValue              *value);
 static gboolean demarshal_basic                 (DBusGValueMarshalCtx      *context,
@@ -72,6 +51,12 @@ static gboolean demarshal_strv                  (DBusGValueMarshalCtx      *cont
                                                 DBusMessageIter           *iter,
                                                 GValue                    *value,
                                                 GError                   **error);
+static gboolean marshal_valuearray              (DBusMessageIter           *iter,
+                                                const GValue              *value);
+static gboolean demarshal_valuearray            (DBusGValueMarshalCtx      *context,
+                                                DBusMessageIter           *iter,
+                                                GValue                    *value,
+                                                GError                   **error);
 static gboolean marshal_variant                 (DBusMessageIter           *iter,
                                                 const GValue              *value);
 static gboolean demarshal_variant               (DBusGValueMarshalCtx      *context,
@@ -122,13 +107,6 @@ static gboolean demarshal_collection_array      (DBusGValueMarshalCtx      *cont
                                                 GValue                    *value,
                                                 GError                   **error);
 
-static gboolean marshal_recurse                 (DBusMessageIter           *iter,
-                                                const GValue              *value);
-static gboolean demarshal_recurse               (DBusGValueMarshalCtx      *context,
-                                                DBusMessageIter           *iter,
-                                                GValue                    *value,
-                                                GError                   **error);
-
 typedef gboolean (*DBusGValueMarshalFunc)       (DBusMessageIter           *iter,
                                                 const GValue              *value);
 typedef gboolean (*DBusGValueDemarshalFunc)     (DBusGValueMarshalCtx      *context,
@@ -215,8 +193,6 @@ dbus_g_value_types_init (void)
   if (types_initialized)
     return;
 
-  g_assert (sizeof (DBusGValueIterator) >= sizeof (DBusMessageIter));
-
   dbus_g_type_specialized_init ();
   dbus_g_type_specialized_builtins_init ();
   
@@ -408,95 +384,6 @@ dbus_g_object_path_get_g_type (void)
   return type_id;
 }
 
-/**
- * Get the GLib type ID for a DBusGValue boxed type.
- *
- * @returns GLib type
- */
-GType
-dbus_g_value_get_g_type (void)
-{
-  static GType type_id = 0;
-
-  if (!type_id)
-    type_id = g_boxed_type_register_static ("DBusGValue",
-                                           dbus_g_value_copy,
-                                           (GBoxedFreeFunc) dbus_g_value_free);
-  return type_id;
-}
-
-void
-dbus_g_value_open (DBusGValue          *value,
-                  DBusGValueIterator  *iter)
-{
-  DBusGValue *real;
-
-  g_return_if_fail (value->type == DBUS_G_VALUE_TYPE_TOPLEVEL);
-
-  real = (DBusGValue*) iter;
-  real->type = DBUS_G_VALUE_TYPE_ITERATOR;
-  real->value.recurse.toplevel = value;
-
-  dbus_message_iter_init (value->value.toplevel.message,
-                         &(real->value.recurse.iterator));
-  value->value.recurse.toplevel = value;
-}
-
-gboolean
-dbus_g_value_iterator_get_values (DBusGValueIterator *iter,
-                                 GError            **error,
-                                 GValue             *first_val,
-                                 ...)
-{
-  GValue *value;
-  va_list args;
-  DBusGValue *iterval;
-
-  va_start (args, first_val);
-
-  iterval = (DBusGValue *) iter;
-
-  value = first_val;
-  do
-    {
-      DBusGValueMarshalCtx context;
-
-      context.gconnection = (iterval->value.recurse.toplevel)->value.toplevel.connection;
-      context.proxy = (iterval->value.recurse.toplevel)->value.toplevel.proxy;
-
-      if (!dbus_gvalue_demarshal (&context,
-                                 &(iterval->value.recurse.iterator),
-                                 value,
-                                 error))
-       return FALSE;
-    } while ((value = va_arg (args, GValue *)) != NULL);
-  
-  return TRUE;
-}
-
-static char *
-dbus_g_value_get_signature (DBusGValue *value)
-{
-  return value->value.toplevel.signature;
-}
-
-static gpointer
-dbus_g_value_copy (gpointer value)
-{
-  /* FIXME */
-  return NULL;
-}
-
-void
-dbus_g_value_free (DBusGValue *value)
-{
-  if (value->type == DBUS_G_VALUE_TYPE_TOPLEVEL)
-    {
-      dbus_message_unref (value->value.toplevel.message);
-      g_free (value->value.toplevel.signature);
-    }
-}
-
 static GType
 signature_iter_to_g_type_dict (const DBusSignatureIter *subiter, gboolean is_client)
 {
@@ -553,27 +440,6 @@ signature_iter_to_g_type_array (DBusSignatureIter *iter, gboolean is_client)
   return G_TYPE_INVALID; 
 }
 
-static gboolean
-signature_iter_to_g_type_struct (DBusSignatureIter *origiter, gboolean is_client)
-{
-  /* FIXME allow structures */
-  return G_TYPE_INVALID;
-#if 0
-  DBusSignatureIter iter;
-  int current_type;
-
-  iter = *origiter;
-
-  while ((current_type = dbus_signature_iter_get_current_type (&iter)) != DBUS_TYPE_INVALID)
-    {
-      subtype = dbus_gtype_from_signature_iter (&iter, is_client);
-      if (subtype == G_TYPE_INVALID)
-       return G_TYPE_INVALID;
-    }
-  return DBUS_TYPE_G_VALUE ();
-#endif
-}
-
 GType
 dbus_gtype_from_signature_iter (DBusSignatureIter *iter, gboolean is_client)
 {
@@ -592,7 +458,9 @@ dbus_gtype_from_signature_iter (DBusSignatureIter *iter, gboolean is_client)
       g_assert (dbus_type_is_container (current_type));
 
       if (current_type == DBUS_TYPE_VARIANT)
-       return g_value_get_type ();
+       return G_TYPE_VALUE;
+      if (current_type == DBUS_TYPE_STRUCT)
+       return G_TYPE_VALUE_ARRAY;
       
       dbus_signature_iter_recurse (iter, &subiter);
 
@@ -604,10 +472,6 @@ 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 if (current_type == DBUS_TYPE_DICT_ENTRY)
-       return G_TYPE_INVALID;
       else
        {
          g_assert_not_reached ();
@@ -626,26 +490,6 @@ dbus_gtype_from_signature (const char *signature, gboolean is_client)
   return dbus_gtype_from_signature_iter (&iter, is_client);
 }
 
-static char *
-dbus_gvalue_to_signature (GValue *value)
-{
-  char *ret;
-
-  ret = dbus_gtype_to_signature (G_VALUE_TYPE (value));
-  if (ret)
-    return ret;
-  else
-    {
-      DBusGValue *val;
-      
-      g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_VALUE);
-
-      val = g_value_get_boxed (value);
-      
-      return dbus_g_value_get_signature (val);
-    }
-}
-
 char *
 dbus_gtype_to_signature (GType gtype)
 {
@@ -688,6 +532,34 @@ dbus_gtype_to_signature (GType gtype)
   return ret;
 }
 
+static char *
+dbus_gvalue_to_signature (const GValue *val)
+{
+  GType gtype;
+
+  gtype = G_VALUE_TYPE (val);
+  if (g_type_is_a (gtype, G_TYPE_VALUE_ARRAY))
+    {
+      GString *str;
+      guint i;
+      GValueArray *array;
+
+      array = g_value_get_boxed (val);
+      
+      str = g_string_new ("");
+      for (i = 0; i < array->n_values; i++)
+       {
+         char *sig;
+         sig = dbus_gvalue_to_signature (g_value_array_get_nth (array, i));
+         g_string_append (str, sig);
+         g_free (sig);
+       }
+      return g_string_free (str, FALSE);
+    }
+  else
+    return dbus_gtype_to_signature (gtype);
+}
+
 GArray *
 dbus_gtypes_from_arg_signature (const char *argsig, gboolean is_client)
 {
@@ -998,6 +870,69 @@ demarshal_strv (DBusGValueMarshalCtx    *context,
 }
 
 static gboolean
+demarshal_valuearray (DBusGValueMarshalCtx    *context,
+                     DBusMessageIter         *iter,
+                     GValue                  *value,
+                     GError                 **error)
+{
+  int current_type;
+  GValueArray *ret;
+  DBusMessageIter subiter;
+
+  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);
+
+  ret = g_value_array_new (12);
+
+  while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
+    {
+      GValue *val;
+      GType elt_type; 
+      char *current_sig;
+
+      g_value_array_append (ret, NULL);
+      val = g_value_array_get_nth (ret, ret->n_values - 1);
+
+      current_sig = dbus_message_iter_get_signature (&subiter);
+      elt_type = dbus_gtype_from_signature (current_sig, TRUE);
+
+      g_free (current_sig);
+      if (elt_type == G_TYPE_INVALID)
+       {
+         g_value_array_free (ret);
+         g_set_error (error,
+                      DBUS_GERROR,
+                      DBUS_GERROR_INVALID_ARGS,
+                      _("Couldn't demarshal argument with signature \"%s\""), current_sig);
+         return FALSE;
+       }
+      
+      g_value_init (val, elt_type);
+
+      if (!dbus_gvalue_demarshal (context, &subiter, val, error))
+       {
+         g_value_array_free (ret);
+         return FALSE;
+       }
+
+      dbus_message_iter_next (&subiter);
+    }
+
+  g_value_set_boxed_take_ownership (value, ret);
+  
+  return TRUE;
+}
+
+static gboolean
 demarshal_map (DBusGValueMarshalCtx    *context,
               DBusMessageIter         *iter,
               GValue                  *value,
@@ -1088,8 +1023,8 @@ get_type_demarshaller (GType type)
   typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
   if (typedata == NULL)
     {
-      if (g_type_is_a (type, DBUS_TYPE_G_VALUE))
-       return demarshal_recurse;
+      if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
+       return demarshal_valuearray;
       if (dbus_g_type_is_collection (type))
        return demarshal_collection;
       if (dbus_g_type_is_map (type))
@@ -1225,15 +1160,6 @@ demarshal_collection_array (DBusGValueMarshalCtx    *context,
   return TRUE;
 }
 
-static gboolean
-demarshal_recurse (DBusGValueMarshalCtx    *context,
-                  DBusMessageIter         *iter,
-                  GValue                  *value,
-                  GError                 **error)
-{
-  return FALSE;
-}
-
 gboolean
 dbus_gvalue_demarshal (DBusGValueMarshalCtx    *context,
                       DBusMessageIter         *iter,
@@ -1493,6 +1419,39 @@ marshal_strv (DBusMessageIter   *iter,
 }
 
 static gboolean
+marshal_valuearray (DBusMessageIter   *iter,
+                   const GValue       *value)
+{
+  GValueArray *array;
+  guint i;
+  DBusMessageIter subiter;
+
+  g_assert (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
+
+  array = g_value_get_boxed (value);
+
+  if (!dbus_message_iter_open_container (iter,
+                                        DBUS_TYPE_STRUCT,
+                                        NULL,
+                                        &subiter))
+    goto oom;
+
+  for (i = 0; i < array->n_values; i++)
+    {
+      if (!dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
+       return FALSE;
+    }
+
+  if (!dbus_message_iter_close_container (iter, &subiter))
+    goto oom;
+
+  return TRUE;
+ oom:
+  g_error ("out of memory");
+  return FALSE;
+}
+
+static gboolean
 marshal_proxy (DBusMessageIter         *iter,
               const GValue            *value)
 {
@@ -1595,10 +1554,10 @@ marshal_map (DBusMessageIter   *iter,
   DBusMessageIter arr_iter;
   gboolean ret;
   struct DBusGLibHashMarshalData hashdata;
+  char *key_sig;
+  char *value_sig;
   GType key_type;
   GType value_type;
-  const char *key_sig;
-  const char *value_sig;
   char *entry_sig;
   char *array_sig;
 
@@ -1612,8 +1571,21 @@ marshal_map (DBusMessageIter   *iter,
   g_assert (dbus_gtype_is_valid_hash_value (value_type));
 
   key_sig = dbus_gtype_to_signature (key_type);
+  if (!key_sig)
+    {
+      g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (key_type));
+      return FALSE;
+    }
   value_sig = dbus_gtype_to_signature (value_type);
+  if (!value_sig)
+    {
+      g_free (key_sig);
+      g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (value_type));
+      return FALSE;
+    }
   entry_sig = g_strdup_printf ("%s%s", key_sig, value_sig);
+  g_free (key_sig);
+  g_free (value_sig);
   array_sig = g_strdup_printf ("%c%s%c",
                               DBUS_DICT_ENTRY_BEGIN_CHAR,
                               entry_sig,
@@ -1660,8 +1632,7 @@ marshal_variant (DBusMessageIter          *iter,
   variant_sig = dbus_gvalue_to_signature (real_value);
   if (variant_sig == NULL)
     {
-      g_warning ("Unsupported value type \"%s\"",
-                g_type_name (value_gtype));
+      g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
       return FALSE;
     }
 
@@ -1691,8 +1662,8 @@ get_type_marshaller (GType type)
   typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
   if (typedata == NULL)
     {
-      if (g_type_is_a (type, DBUS_TYPE_G_VALUE))
-       return marshal_recurse;
+      if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
+       return marshal_valuearray;
       if (dbus_g_type_is_collection (type))
        return marshal_collection;
       if (dbus_g_type_is_map (type))
@@ -1757,8 +1728,12 @@ marshal_collection_ptrarray (DBusMessageIter         *iter,
   if (!data.marshaller)
     return FALSE;
 
-  /* FIXME - this means we can't send an array of DBusGValue right now... */
   elt_sig = dbus_gtype_to_signature (elt_gtype);
+  if (!elt_sig)
+    {
+      g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
+      return FALSE;
+    }
 
   if (!dbus_message_iter_open_container (iter,
                                         DBUS_TYPE_ARRAY,
@@ -1797,7 +1772,11 @@ marshal_collection_array (DBusMessageIter   *iter,
   elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
   g_assert (dbus_g_type_is_fixed (elt_gtype));
   subsignature_str = dbus_gtype_to_signature (elt_gtype);
-  g_assert (subsignature_str != NULL);
+  if (!subsignature_str)
+    {
+      g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
+      return FALSE;
+    }
   
   elt_size = dbus_g_type_fixed_get_size (elt_gtype);
 
@@ -1828,13 +1807,6 @@ marshal_collection_array (DBusMessageIter   *iter,
   return FALSE;
 }
 
-static gboolean
-marshal_recurse (DBusMessageIter         *iter,
-                const GValue            *value)
-{
-  return FALSE;
-}
-
 gboolean
 dbus_gvalue_marshal (DBusMessageIter         *iter,
                     const GValue       *value)
@@ -1889,6 +1861,10 @@ _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);
   assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
index fb157a7..dac1f82 100644 (file)
@@ -41,12 +41,21 @@ main (int argc, char **argv)
   GError *error = NULL;
   char **reply_list;
   char **reply_ptr;
-  DBusGValue *hello_reply_struct;
+  GValueArray *hello_reply_struct;
   GHashTable *hello_reply_dict;
   char *introspect_data;
+  guint i;
 
   g_type_init ();
 
+  {
+    GLogLevelFlags fatal_mask;
+    
+    fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
+    fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
+    g_log_set_always_fatal (fatal_mask);
+  }
+
   bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
   if (!bus)
     lose_gerror ("Couldn't connect to session bus", error);
@@ -62,12 +71,10 @@ main (int argc, char **argv)
     lose_gerror ("Failed to complete HelloWorld", error);
 
   
-  /* FIXME - we don't support recursive values yet */
-#if 0  
   if (!dbus_g_proxy_call (remote_object, "GetTuple", &error,
-                         DBUS_TYPE_G_VALUE, &hello_reply_struct, G_TYPE_INVALID))
+                         G_TYPE_INVALID,
+                         G_TYPE_VALUE_ARRAY, &hello_reply_struct, G_TYPE_INVALID))
     lose_gerror ("Failed to complete GetTuple", error);
-#endif  
   
   if (!dbus_g_proxy_call (remote_object, "GetDict", &error,
                          G_TYPE_INVALID,
@@ -80,11 +87,18 @@ main (int argc, char **argv)
   printf ("\n");
   g_strfreev (reply_list);
 
-  /* FIXME; do something with hello_reply_struct */
-#if 0
-  dbus_g_value_free (hello_reply_struct);
+  for (i = 0; i < hello_reply_struct->n_values; i++)
+    {
+      GValue strval = { 0, };
+
+      g_value_init (&strval, G_TYPE_STRING);
+      if (!g_value_transform (g_value_array_get_nth (hello_reply_struct, i), &strval))
+       g_value_set_static_string (&strval, "(couldn't transform to string)");
+      g_print ("%s: %s\n", g_type_name (G_VALUE_TYPE (g_value_array_get_nth (hello_reply_struct, i))),
+              g_value_get_string (&strval));
+    }
+  g_value_array_free (hello_reply_struct);
   printf ("\n");
-#endif
 
   g_hash_table_foreach (hello_reply_dict, print_hash_value, NULL);
   g_hash_table_destroy (hello_reply_dict);
index d1f8c62..5e58175 100644 (file)
@@ -51,7 +51,7 @@ struct SomeObjectClass
 G_DEFINE_TYPE(SomeObject, some_object, G_TYPE_OBJECT)
 
 gboolean some_object_hello_world (SomeObject *obj, const char *hello_message, char ***ret, GError **error);
-gboolean some_object_get_tuple (SomeObject *obj, DBusGValue **ret, GError **error);
+gboolean some_object_get_tuple (SomeObject *obj, GValueArray **ret, GError **error);
 gboolean some_object_get_dict (SomeObject *obj, GHashTable **ret, GError **error);
 
 #include "example-service-glue.h"
@@ -79,9 +79,16 @@ some_object_hello_world (SomeObject *obj, const char *hello_message, char ***ret
 }
 
 gboolean
-some_object_get_tuple (SomeObject *obj, DBusGValue **ret, GError **error)
+some_object_get_tuple (SomeObject *obj, GValueArray **ret, GError **error)
 {
-  /* FIXME */
+  *ret = g_value_array_new (6);
+  g_value_array_prepend (*ret, NULL);
+  g_value_init (g_value_array_get_nth (*ret, 0), G_TYPE_STRING);
+  g_value_set_string (g_value_array_get_nth (*ret, 0), "hello");
+  g_value_array_prepend (*ret, NULL);
+  g_value_init (g_value_array_get_nth (*ret, 0), G_TYPE_UINT);
+  g_value_set_uint (g_value_array_get_nth (*ret, 0), 42);
+  
   return TRUE;
 }
 
@@ -105,6 +112,14 @@ main (int argc, char **argv)
   guint request_name_result;
 
   g_type_init ();
+
+  {
+    GLogLevelFlags fatal_mask;
+    
+    fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
+    fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
+    g_log_set_always_fatal (fatal_mask);
+  }
   
   dbus_g_object_type_install_info (SOME_TYPE_OBJECT, &dbus_glib_some_object_object_info);
 
index 786235d..962db15 100644 (file)
@@ -885,6 +885,51 @@ main (int argc, char **argv)
   run_mainloop ();
 
   {
+    GValueArray *vals;
+    GValueArray *vals_ret;
+    GValue *val;
+
+    vals = g_value_array_new (3);
+
+    g_value_array_append (vals, NULL);
+    g_value_init (g_value_array_get_nth (vals, vals->n_values - 1), G_TYPE_STRING);
+    g_value_set_string (g_value_array_get_nth (vals, 0), "foo");
+
+    g_value_array_append (vals, NULL);
+    g_value_init (g_value_array_get_nth (vals, vals->n_values - 1), G_TYPE_UINT);
+    g_value_set_uint (g_value_array_get_nth (vals, vals->n_values - 1), 42);
+
+    g_value_array_append (vals, NULL);
+    g_value_init (g_value_array_get_nth (vals, vals->n_values - 1), G_TYPE_VALUE);
+    val = g_new0 (GValue, 1);
+    g_value_init (val, G_TYPE_UCHAR);
+    g_value_set_uchar (val, '!');
+    g_value_set_boxed (g_value_array_get_nth (vals, vals->n_values - 1), val);
+
+    vals_ret = NULL;
+    g_print ("Calling SendCar\n");
+    if (!dbus_g_proxy_call (proxy, "SendCar", &error,
+                           G_TYPE_VALUE_ARRAY, vals,
+                           G_TYPE_INVALID,
+                           G_TYPE_VALUE_ARRAY, &vals_ret,
+                           G_TYPE_INVALID))
+      lose_gerror ("Failed to complete SendCar call", error);
+
+    g_assert (vals_ret != NULL);
+    g_assert (vals_ret->n_values == 2);
+
+    g_assert (G_VALUE_HOLDS_UINT (g_value_array_get_nth (vals_ret, 0)));
+    g_assert (g_value_get_uint (g_value_array_get_nth (vals_ret, 0)) == 43);
+    
+    g_assert (G_VALUE_TYPE (g_value_array_get_nth (vals_ret, 1)) == DBUS_TYPE_G_OBJECT_PATH);
+    g_assert (!strcmp ("/org/freedesktop/DBus/Tests/MyTestObject2",
+                      g_value_get_boxed (g_value_array_get_nth (vals_ret, 1))));
+
+    g_value_array_free (vals);
+    g_value_array_free (vals_ret);
+  }
+
+  {
     GValue *val;
     GHashTable *table;
     GHashTable *ret_table;
index e44310f..b0043e8 100644 (file)
@@ -80,6 +80,8 @@ gboolean my_object_many_uppercase (MyObject *obj, const char * const *in, char *
 
 gboolean my_object_str_hash_len (MyObject *obj, GHashTable *table, guint *len, GError **error);
 
+gboolean my_object_send_car (MyObject *obj, GValueArray *invals, GValueArray **outvals, GError **error);
+
 gboolean my_object_get_hash (MyObject *obj, GHashTable **table, GError **error);
 
 gboolean my_object_increment_val (MyObject *obj, GError **error);
@@ -502,6 +504,32 @@ my_object_str_hash_len (MyObject *obj, GHashTable *table, guint *len, GError **e
 }
 
 gboolean
+my_object_send_car (MyObject *obj, GValueArray *invals, GValueArray **outvals, GError **error)
+{
+  if (invals->n_values != 3
+      || G_VALUE_TYPE (g_value_array_get_nth (invals, 0)) != G_TYPE_STRING
+      || G_VALUE_TYPE (g_value_array_get_nth (invals, 1)) != G_TYPE_UINT
+      || G_VALUE_TYPE (g_value_array_get_nth (invals, 2)) != G_TYPE_VALUE)
+    {
+      g_set_error (error,
+                  MY_OBJECT_ERROR,
+                  MY_OBJECT_ERROR_FOO,
+                  "invalid incoming values");
+      return FALSE;
+    }
+  *outvals = g_value_array_new (2);
+  g_value_array_append (*outvals, NULL);
+  g_value_init (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1), G_TYPE_UINT);
+  g_value_set_uint (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1),
+                   g_value_get_uint (g_value_array_get_nth (invals, 1)) + 1);
+  g_value_array_append (*outvals, NULL);
+  g_value_init (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1), DBUS_TYPE_G_OBJECT_PATH);
+  g_value_set_boxed (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1),
+                    g_strdup ("/org/freedesktop/DBus/Tests/MyTestObject2"));
+  return TRUE;
+}
+
+gboolean
 my_object_get_hash (MyObject *obj, GHashTable **ret, GError **error)
 {
   GHashTable *table;
index 4ea2b2b..f63bead 100644 (file)
       <arg type="u" direction="out"/>
     </method>
 
+    <method name="SendCar">
+      <arg type="(suv)" direction="in"/>
+      <arg type="(uo)" direction="out"/>
+    </method>
+
     <method name="GetHash">
       <arg type="a{ss}" direction="out"/>
     </method>