Index: create.patch.sh
===================================================================
--- create.patch.sh (nonexistent)
+++ create.patch.sh (revision 5)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=0.112
+
+tar --files-from=file.list -xzvf ../dbus-glib-$VERSION.tar.gz
+mv dbus-glib-$VERSION dbus-glib-$VERSION-orig
+
+cp -rf ./dbus-glib-$VERSION-new ./dbus-glib-$VERSION
+
+diff --unified -Nr dbus-glib-$VERSION-orig dbus-glib-$VERSION > dbus-glib-$VERSION-deprecated-array.patch
+
+mv dbus-glib-$VERSION-deprecated-array.patch ../patches
+
+rm -rf ./dbus-glib-$VERSION
+rm -rf ./dbus-glib-$VERSION-orig
Property changes on: create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: dbus-glib-0.112-new/dbus/dbus-binding-tool-glib.c
===================================================================
--- dbus-glib-0.112-new/dbus/dbus-binding-tool-glib.c (nonexistent)
+++ dbus-glib-0.112-new/dbus/dbus-binding-tool-glib.c (revision 5)
@@ -0,0 +1,1705 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-binding-tool-glib.c: Output C glue
+ *
+ * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
+ * Copyright (C) 2005 Nokia
+ *
+ * SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <config.h>
+#include "dbus/dbus-glib.h"
+#include "dbus-gidl.h"
+#include "dbus-gparser.h"
+#include "dbus-gutils.h"
+#include "dbus-gtype-specialized.h"
+#include "dbus-gsignature.h"
+#include "dbus-gvalue-utils.h"
+#include "dbus-glib-tool.h"
+#include "dbus-binding-tool-glib.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Remember to grep for ->format_version in the code if you change this,
+ * most changes should be in dbus-gobject.c. */
+#define FORMAT_VERSION 1
+
+#define MARSHAL_PREFIX "dbus_glib_marshal_"
+
+typedef struct
+{
+ gboolean ignore_unsupported;
+ const char* prefix;
+ GIOChannel *channel;
+
+ GError **error;
+
+ GHashTable *generated;
+ GString *blob;
+ GString *signal_blob;
+ GString *property_blob;
+ guint count;
+} DBusBindingToolCData;
+
+static gboolean gather_marshallers (BaseInfo *base, DBusBindingToolCData *data, GError **error);
+static gboolean generate_glue_toplevel (BaseInfo *base, DBusBindingToolCData *data, GError **error);
+static gboolean generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error);
+static gboolean generate_client_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error);
+
+static const char *
+dbus_g_type_get_marshal_name (GType gtype)
+{
+ switch (G_TYPE_FUNDAMENTAL (gtype))
+ {
+ case G_TYPE_NONE:
+ return "NONE";
+ case G_TYPE_BOOLEAN:
+ return "BOOLEAN";
+ case G_TYPE_UCHAR:
+ return "UCHAR";
+ case G_TYPE_INT:
+ return "INT";
+ case G_TYPE_UINT:
+ return "UINT";
+ case G_TYPE_INT64:
+ return "INT64";
+ case G_TYPE_UINT64:
+ return "UINT64";
+ case G_TYPE_DOUBLE:
+ return "DOUBLE";
+ case G_TYPE_STRING:
+ return "STRING";
+ case G_TYPE_POINTER:
+ return "POINTER";
+ case G_TYPE_BOXED:
+ return "BOXED";
+ case G_TYPE_OBJECT:
+ return "OBJECT";
+ default:
+ return NULL;
+ }
+}
+
+/* This entire function is kind of...ugh. */
+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);
+ if (_dbus_g_type_is_fixed (subtype))
+ return "GArray";
+ else
+ return "GPtrArray";
+ }
+
+ if (dbus_g_type_is_map (gtype))
+ return "GHashTable";
+
+ if (g_type_is_a (gtype, G_TYPE_STRING))
+ return "char *";
+
+ /* This one is even more hacky...we get an extra *
+ * because G_TYPE_STRV is a G_TYPE_BOXED
+ */
+ if (g_type_is_a (gtype, G_TYPE_STRV))
+ return "char *";
+
+ if (g_type_is_a (gtype, DBUS_TYPE_G_OBJECT_PATH))
+ return "char";
+
+ if (g_type_is_a (gtype, DBUS_TYPE_G_SIGNATURE))
+ return "char";
+
+ return g_type_name (gtype);
+}
+
+static gboolean
+compute_gsignature (MethodInfo *method, GType *rettype, GArray **params, GError **error)
+{
+ GSList *elt;
+ GType retval_type;
+ GArray *ret;
+ gboolean is_async;
+ const char *arg_type;
+ gboolean retval_signals_error;
+
+ is_async = method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_ASYNC) != NULL;
+ retval_signals_error = FALSE;
+
+ ret = g_array_new (TRUE, TRUE, sizeof (GType));
+
+ if (is_async)
+ retval_type = G_TYPE_NONE;
+ else
+ {
+ gboolean found_retval;
+
+ /* Look for return value */
+ found_retval = FALSE;
+ for (elt = method_info_get_args (method); elt; elt = elt->next)
+ {
+ ArgInfo *arg = elt->data;
+ const char *returnval_annotation;
+
+ returnval_annotation = arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL);
+ if (returnval_annotation != NULL)
+ {
+ arg_type = arg_info_get_type (arg);
+ retval_type = _dbus_gtype_from_signature (arg_type, FALSE);
+ if (retval_type == G_TYPE_INVALID)
+ goto invalid_type;
+ found_retval = TRUE;
+ if (!strcmp (returnval_annotation, "error"))
+ retval_signals_error = TRUE;
+ break;
+ }
+ }
+ if (!found_retval)
+ {
+ retval_type = G_TYPE_BOOLEAN;
+ retval_signals_error = TRUE;
+ }
+ }
+
+ *rettype = retval_type;
+
+ /* Handle all input arguments */
+ for (elt = method_info_get_args (method); elt; elt = elt->next)
+ {
+ ArgInfo *arg = elt->data;
+ if (arg_info_get_direction (arg) == ARG_IN)
+ {
+ GType gtype;
+
+ arg_type = arg_info_get_type (arg);
+ gtype = _dbus_gtype_from_signature (arg_type, FALSE);
+ if (gtype == G_TYPE_INVALID)
+ goto invalid_type;
+
+ g_array_append_val (ret, gtype);
+ }
+ }
+
+ if (!is_async)
+ {
+ /* Append pointer for each out arg storage */
+ for (elt = method_info_get_args (method); elt; elt = elt->next)
+ {
+ ArgInfo *arg = elt->data;
+
+ /* Skip return value */
+ if (arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL) != NULL)
+ continue;
+
+ if (arg_info_get_direction (arg) == ARG_OUT)
+ {
+ GType gtype;
+ arg_type = arg_info_get_type (arg);
+ gtype = _dbus_gtype_from_signature (arg_type, FALSE);
+ if (gtype == G_TYPE_INVALID)
+ goto invalid_type;
+ /* We actually just need a pointer for the return value
+ storage */
+ gtype = G_TYPE_POINTER;
+ g_array_append_val (ret, gtype);
+ }
+ }
+
+ if (retval_signals_error)
+ {
+ /* Final GError parameter */
+ GType gtype = G_TYPE_POINTER;
+ g_array_append_val (ret, gtype);
+ }
+ }
+ else
+ {
+ /* Context pointer */
+ GType gtype = G_TYPE_POINTER;
+ g_array_append_val (ret, gtype);
+ }
+
+ *params = ret;
+ return TRUE;
+
+ invalid_type:
+ g_set_error (error,
+ DBUS_BINDING_TOOL_ERROR,
+ DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
+ "Unsupported conversion from D-BUS type %s to glib-genmarshal type",
+ arg_type);
+ return FALSE;
+}
+
+
+static char *
+compute_marshaller (MethodInfo *method, GError **error)
+{
+ GArray *signature;
+ GType rettype;
+ const char *marshal_name;
+ GString *ret;
+ guint i;
+
+ if (!compute_gsignature (method, &rettype, &signature, error))
+ return NULL;
+
+ ret = g_string_new ("");
+ marshal_name = dbus_g_type_get_marshal_name (rettype);
+ g_assert (marshal_name != NULL);
+ g_string_append (ret, marshal_name);
+ g_string_append_c (ret, ':');
+ for (i = 0; i < signature->len; i++)
+ {
+ marshal_name = dbus_g_type_get_marshal_name (g_array_index (signature, GType, i));
+ g_assert (marshal_name != NULL);
+ g_string_append (ret, marshal_name);
+ if (i < signature->len - 1)
+ g_string_append_c (ret, ',');
+ }
+ if (signature->len == 0)
+ {
+ marshal_name = dbus_g_type_get_marshal_name (G_TYPE_NONE);
+ g_assert (marshal_name != NULL);
+ g_string_append (ret, marshal_name);
+ }
+ g_array_free (signature, TRUE);
+ return g_string_free (ret, FALSE);
+}
+
+static char *
+compute_marshaller_name (MethodInfo *method, const char *prefix, GError **error)
+{
+ GString *ret;
+ GArray *signature;
+ GType rettype;
+ const char *marshal_name;
+ guint i;
+
+ if (!compute_gsignature (method, &rettype, &signature, error))
+ return NULL;
+
+ ret = g_string_new (MARSHAL_PREFIX);
+ g_string_append (ret, prefix);
+ g_string_append_c (ret, '_');
+
+ marshal_name = dbus_g_type_get_marshal_name (rettype);
+ g_assert (marshal_name != NULL);
+ g_string_append (ret, marshal_name);
+ g_string_append (ret, "__");
+ for (i = 0; i < signature->len; i++)
+ {
+ marshal_name = dbus_g_type_get_marshal_name (g_array_index (signature, GType, i));
+ g_assert (marshal_name != NULL);
+ g_string_append (ret, marshal_name);
+ if (i < signature->len - 1)
+ g_string_append_c (ret, '_');
+ }
+ if (signature->len == 0)
+ {
+ marshal_name = dbus_g_type_get_marshal_name (G_TYPE_NONE);
+ g_assert (marshal_name != NULL);
+ g_string_append (ret, marshal_name);
+ }
+ g_array_free (signature, TRUE);
+ return g_string_free (ret, FALSE);
+}
+
+static gboolean
+gather_marshallers_list (GSList *list, DBusBindingToolCData *data, GError **error)
+{
+ GSList *tmp;
+
+ tmp = list;
+ while (tmp != NULL)
+ {
+ if (!gather_marshallers (tmp->data, data, error))
+ return FALSE;
+ tmp = tmp->next;
+ }
+ return TRUE;
+}
+
+static gboolean
+gather_marshallers (BaseInfo *base, DBusBindingToolCData *data, GError **error)
+{
+ if (base_info_get_type (base) == INFO_TYPE_NODE)
+ {
+ if (!gather_marshallers_list (node_info_get_nodes ((NodeInfo *) base),
+ data, error))
+ return FALSE;
+ if (!gather_marshallers_list (node_info_get_interfaces ((NodeInfo *) base),
+ data, error))
+ return FALSE;
+ }
+ else
+ {
+ InterfaceInfo *interface;
+ GSList *methods;
+ GSList *tmp;
+ const char *interface_c_name;
+
+ interface = (InterfaceInfo *) base;
+ interface_c_name = interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_C_SYMBOL);
+ if (interface_c_name == NULL)
+ {
+ if (!data->prefix)
+ return TRUE;
+ }
+
+ methods = interface_info_get_methods (interface);
+
+ /* Generate the necessary marshallers for the methods. */
+
+ for (tmp = methods; tmp != NULL; tmp = g_slist_next (tmp))
+ {
+ MethodInfo *method;
+ char *marshaller_name;
+
+ method = (MethodInfo *) tmp->data;
+
+ marshaller_name = compute_marshaller (method, error);
+ if (!marshaller_name)
+ return FALSE;
+
+ if (g_hash_table_lookup (data->generated, marshaller_name))
+ {
+ g_free (marshaller_name);
+ continue;
+ }
+
+ g_hash_table_insert (data->generated, marshaller_name, NULL);
+ }
+
+ }
+ return TRUE;
+}
+
+static gboolean
+generate_glue_list (GSList *list, DBusBindingToolCData *data, GError **error)
+{
+ GSList *tmp;
+
+ tmp = list;
+ while (tmp != NULL)
+ {
+ if (!generate_glue (tmp->data, data, error))
+ return FALSE;
+ tmp = tmp->next;
+ }
+ return TRUE;
+}
+
+#define WRITE_OR_LOSE(x) do { gsize bytes_written; if (!g_io_channel_write_chars (channel, x, -1, &bytes_written, error)) goto io_lose; } while (0)
+
+static gboolean
+write_printf_to_iochannel (const char *fmt, GIOChannel *channel, GError **error, ...)
+{
+ char *str;
+ va_list args;
+ GIOStatus status;
+ gsize written;
+ gboolean ret;
+
+ va_start (args, error);
+
+ str = g_strdup_vprintf (fmt, args);
+ if ((status = g_io_channel_write_chars (channel, str, -1, &written, error)) == G_IO_STATUS_NORMAL)
+ ret = TRUE;
+ else
+ ret = FALSE;
+
+ g_free (str);
+
+ va_end (args);
+
+ return ret;
+}
+
+static gboolean
+write_quoted_string (GIOChannel *channel, GString *string, GError **error)
+{
+ guint i;
+
+ WRITE_OR_LOSE ("\"");
+ for (i = 0; i < string->len; i++)
+ {
+ if (string->str[i] != '\0')
+ {
+ if (!g_io_channel_write_chars (channel, string->str + i, 1, NULL, error))
+ return FALSE;
+ }
+ else
+ {
+ if (!g_io_channel_write_chars (channel, "\\0", -1, NULL, error))
+ return FALSE;
+ }
+ }
+ WRITE_OR_LOSE ("\\0\"");
+ return TRUE;
+ io_lose:
+ return FALSE;
+}
+
+static gboolean
+generate_glue_toplevel (BaseInfo *base, DBusBindingToolCData *data, GError **error)
+{
+ GString *object_introspection_data_blob;
+ GIOChannel *channel;
+
+ channel = data->channel;
+
+ object_introspection_data_blob = g_string_new_len ("", 0);
+ data->blob = object_introspection_data_blob;
+ data->count = 0;
+
+ data->signal_blob = g_string_new_len ("", 0);
+ data->property_blob = g_string_new_len ("", 0);
+
+ if (!write_printf_to_iochannel ("static const DBusGMethodInfo dbus_glib_%s_methods[] = {\n", channel, error, data->prefix))
+ goto io_lose;
+
+ if (!generate_glue_list (node_info_get_nodes ((NodeInfo *) base),
+ data, error))
+ return FALSE;
+ if (!generate_glue_list (node_info_get_interfaces ((NodeInfo *) base),
+ data, error))
+ return FALSE;
+
+ WRITE_OR_LOSE ("};\n\n");
+ /* Information about the object. */
+
+ if (!write_printf_to_iochannel ("const DBusGObjectInfo dbus_glib_%s_object_info = { %d,\n",
+ channel, error, data->prefix, FORMAT_VERSION))
+ goto io_lose;
+ if (!write_printf_to_iochannel (" dbus_glib_%s_methods,\n", channel, error, data->prefix))
+ goto io_lose;
+ if (!write_printf_to_iochannel (" %d,\n", channel, error, data->count))
+ goto io_lose;
+ if (!write_quoted_string (channel, object_introspection_data_blob, error))
+ goto io_lose;
+ WRITE_OR_LOSE (",\n");
+ if (!write_quoted_string (channel, data->signal_blob, error))
+ goto io_lose;
+ WRITE_OR_LOSE (",\n");
+ if (!write_quoted_string (channel, data->property_blob, error))
+ goto io_lose;
+ WRITE_OR_LOSE ("\n};\n\n");
+ g_string_free (object_introspection_data_blob, TRUE);
+ g_string_free (data->signal_blob, TRUE);
+ g_string_free (data->property_blob, TRUE);
+ data->signal_blob = NULL;
+ data->property_blob = NULL;
+ return TRUE;
+io_lose:
+ return FALSE;
+}
+
+static gboolean
+generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
+{
+ if (base_info_get_type (base) == INFO_TYPE_NODE)
+ {
+ if (!generate_glue_list (node_info_get_nodes ((NodeInfo *) base),
+ data, error))
+ return FALSE;
+ if (!generate_glue_list (node_info_get_interfaces ((NodeInfo *) base),
+ data, error))
+ return FALSE;
+ }
+ else
+ {
+ GIOChannel *channel;
+ InterfaceInfo *interface;
+ GSList *methods;
+ GSList *signals;
+ GSList *properties;
+ GSList *tmp;
+ const char *interface_c_name;
+ GString *object_introspection_data_blob;
+
+ channel = data->channel;
+ object_introspection_data_blob = data->blob;
+
+ interface = (InterfaceInfo *) base;
+ interface_c_name = interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_C_SYMBOL);
+ if (interface_c_name == NULL)
+ {
+ if (data->prefix == NULL)
+ return TRUE;
+ interface_c_name = data->prefix;
+ }
+
+ methods = interface_info_get_methods (interface);
+
+ /* Table of marshalled methods. */
+
+ for (tmp = methods; tmp != NULL; tmp = g_slist_next (tmp))
+ {
+ MethodInfo *method;
+ char *marshaller_name;
+ char *method_c_name;
+ gboolean async = FALSE;
+ GSList *args;
+ gboolean found_retval = FALSE;
+ guint found_out_args = 0;
+
+ method = (MethodInfo *) tmp->data;
+ method_c_name = g_strdup (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_C_SYMBOL));
+ if (method_c_name == NULL)
+ {
+ char *method_name_uscored;
+ method_name_uscored = _dbus_gutils_wincaps_to_uscore (method_info_get_name (method));
+ method_c_name = g_strdup_printf ("%s_%s",
+ interface_c_name,
+ method_name_uscored);
+ g_free (method_name_uscored);
+ }
+
+ if (!write_printf_to_iochannel (" { (GCallback) %s, ", channel, error,
+ method_c_name))
+ {
+ g_free (method_c_name);
+ goto io_lose;
+ }
+ g_free (method_c_name);
+
+ marshaller_name = compute_marshaller_name (method, data->prefix, error);
+ if (!marshaller_name)
+ goto io_lose;
+
+ if (!write_printf_to_iochannel ("%s, %d },\n", channel, error,
+ marshaller_name,
+ object_introspection_data_blob->len))
+ {
+ g_free (marshaller_name);
+ goto io_lose;
+ }
+
+ if (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_ASYNC) != NULL)
+ async = TRUE;
+
+ /* Object method data blob format:
+ * <iface>\0<name>\0(<argname>\0<argdirection>\0<argtype>\0)*\0
+ */
+
+ g_string_append (object_introspection_data_blob, interface_info_get_name (interface));
+ g_string_append_c (object_introspection_data_blob, '\0');
+
+ g_string_append (object_introspection_data_blob, method_info_get_name (method));
+ g_string_append_c (object_introspection_data_blob, '\0');
+
+ g_string_append_c (object_introspection_data_blob, async ? 'A' : 'S');
+ g_string_append_c (object_introspection_data_blob, '\0');
+
+ for (args = method_info_get_args (method); args; args = args->next)
+ {
+ ArgInfo *arg;
+ char direction;
+ const char *returnval_annotation;
+
+ arg = args->data;
+
+ g_string_append (object_introspection_data_blob, arg_info_get_name (arg));
+ g_string_append_c (object_introspection_data_blob, '\0');
+
+ switch (arg_info_get_direction (arg))
+ {
+ case ARG_IN:
+ direction = 'I';
+ break;
+ case ARG_OUT:
+ direction = 'O';
+ found_out_args++;
+ break;
+ case ARG_INVALID:
+ default:
+ g_assert_not_reached ();
+ direction = 0; /* silence gcc */
+ break;
+ }
+ g_string_append_c (object_introspection_data_blob, direction);
+ g_string_append_c (object_introspection_data_blob, '\0');
+
+ if (arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_CONST) != NULL)
+ {
+ if (arg_info_get_direction (arg) == ARG_IN)
+ {
+ g_set_error (error,
+ DBUS_BINDING_TOOL_ERROR,
+ DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
+ "Input argument \"%s\" cannot have const annotation in method \"%s\" of interface \"%s\"\n",
+ arg_info_get_name (arg),
+ method_info_get_name (method),
+ interface_info_get_name (interface));
+ return FALSE;
+ }
+ g_string_append_c (object_introspection_data_blob, 'C');
+ g_string_append_c (object_introspection_data_blob, '\0');
+ }
+ else if (arg_info_get_direction (arg) == ARG_OUT)
+ {
+ g_string_append_c (object_introspection_data_blob, 'F');
+ g_string_append_c (object_introspection_data_blob, '\0');
+ }
+
+ returnval_annotation = arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL);
+ if (returnval_annotation != NULL)
+ {
+ GType gtype;
+
+ if (found_retval)
+ {
+ g_set_error (error,
+ DBUS_BINDING_TOOL_ERROR,
+ DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
+ "Multiple arguments with return value annotation in method \"%s\" of interface \"%s\"\n",
+ method_info_get_name (method),
+ interface_info_get_name (interface));
+ return FALSE;
+ }
+ found_retval = TRUE;
+ if (arg_info_get_direction (arg) == ARG_IN)
+ {
+ g_set_error (error,
+ DBUS_BINDING_TOOL_ERROR,
+ DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
+ "Input argument \"%s\" cannot have return value annotation in method \"%s\" of interface \"%s\"\n",
+ arg_info_get_name (arg),
+ method_info_get_name (method),
+ interface_info_get_name (interface));
+ return FALSE;
+ }
+
+ if (found_out_args != 1)
+ {
+ g_set_error (error,
+ DBUS_BINDING_TOOL_ERROR,
+ DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
+ "An output <arg> after the first cannot have the ReturnVal annotation, in argument \"%s\" of method \"%s\" of interface \"%s\"\n",
+ arg_info_get_name (arg),
+ method_info_get_name (method),
+ interface_info_get_name (interface));
+ return FALSE;
+ }
+
+ if (!strcmp ("", returnval_annotation))
+ g_string_append_c (object_introspection_data_blob, 'R');
+ else if (!strcmp ("error", returnval_annotation))
+ {
+ gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+ if (!_dbus_gtype_can_signal_error (gtype))
+ {
+ g_set_error (error,
+ DBUS_BINDING_TOOL_ERROR,
+ DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
+ "Output argument \"%s\" cannot signal error with type \"%s\" in method \"%s\" of interface \"%s\"\n",
+ arg_info_get_name (arg),
+ g_type_name (gtype),
+ method_info_get_name (method),
+ interface_info_get_name (interface));
+ return FALSE;
+ }
+ g_string_append_c (object_introspection_data_blob, 'E');
+ }
+ else
+ {
+ g_set_error (error,
+ DBUS_BINDING_TOOL_ERROR,
+ DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
+ "Invalid ReturnVal annotation for argument \"%s\" in method \"%s\" of interface \"%s\"\n",
+ arg_info_get_name (arg),
+ method_info_get_name (method),
+ interface_info_get_name (interface));
+ return FALSE;
+ }
+
+ g_string_append_c (object_introspection_data_blob, '\0');
+ }
+ else if (arg_info_get_direction (arg) == ARG_OUT)
+ {
+ g_string_append_c (object_introspection_data_blob, 'N');
+ g_string_append_c (object_introspection_data_blob, '\0');
+ }
+
+ g_string_append (object_introspection_data_blob, arg_info_get_type (arg));
+ g_string_append_c (object_introspection_data_blob, '\0');
+ }
+
+ g_string_append_c (object_introspection_data_blob, '\0');
+
+ data->count++;
+ }
+
+ signals = interface_info_get_signals (interface);
+
+ for (tmp = signals; tmp != NULL; tmp = g_slist_next (tmp))
+ {
+ SignalInfo *sig;
+
+ sig = tmp->data;
+
+ g_string_append (data->signal_blob, interface_info_get_name (interface));
+ g_string_append_c (data->signal_blob, '\0');
+ g_string_append (data->signal_blob, signal_info_get_name (sig));
+ g_string_append_c (data->signal_blob, '\0');
+ }
+
+ properties = interface_info_get_properties (interface);
+
+ for (tmp = properties; tmp != NULL; tmp = g_slist_next (tmp))
+ {
+ PropertyInfo *prop;
+ PropertyAccessFlags access_flags;
+ const char *access_string;
+ char *uscored;
+
+ prop = tmp->data;
+
+ access_flags = property_info_get_access (prop);
+ if ((access_flags & PROPERTY_READ) && (access_flags & PROPERTY_WRITE))
+ access_string = "readwrite";
+ else if (access_flags & PROPERTY_READ)
+ access_string = "read";
+ else if (access_flags & PROPERTY_WRITE)
+ access_string = "write";
+ else
+ continue;
+
+ /* We append both in the blob so we have to malloc() less when processing
+ * properties */
+ uscored = _dbus_gutils_wincaps_to_uscore (property_info_get_name (prop));
+
+ g_string_append (data->property_blob, interface_info_get_name (interface));
+ g_string_append_c (data->property_blob, '\0');
+ g_string_append (data->property_blob, property_info_get_name (prop));
+ g_string_append_c (data->property_blob, '\0');
+ g_string_append (data->property_blob, uscored);
+ g_string_append_c (data->property_blob, '\0');
+ g_string_append (data->property_blob, access_string);
+ g_string_append_c (data->property_blob, '\0');
+
+ g_free (uscored);
+ }
+ }
+ return TRUE;
+ io_lose:
+ return FALSE;
+}
+
+static void
+write_marshaller (gpointer key, gpointer value, gpointer user_data)
+{
+ DBusBindingToolCData *data;
+ const char *marshaller;
+ gsize bytes_written;
+
+ data = user_data;
+ marshaller = key;
+
+ if (data->error && *data->error)
+ return;
+
+ if (g_io_channel_write_chars (data->channel, marshaller, -1, &bytes_written, data->error) == G_IO_STATUS_NORMAL)
+ g_io_channel_write_chars (data->channel, "\n", -1, &bytes_written, data->error);
+}
+
+gboolean
+dbus_binding_tool_output_glib_server (BaseInfo *info, GIOChannel *channel, const char *prefix, GError **error)
+{
+ gboolean ret;
+ GPtrArray *argv;
+ gint child_stdout;
+ GIOChannel *genmarshal_stdout;
+ GPid child_pid;
+ DBusBindingToolCData data;
+ char *tempfile_name;
+ gint tempfile_fd;
+ GIOStatus iostatus;
+ char buf[4096];
+ gsize bytes_read, bytes_written;
+
+ memset (&data, 0, sizeof (data));
+
+ dbus_g_type_specialized_init ();
+ _dbus_g_type_specialized_builtins_init ();
+
+ data.prefix = prefix;
+ data.generated = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
+ data.error = error;
+ genmarshal_stdout = NULL;
+ tempfile_name = NULL;
+
+ if (!gather_marshallers (info, &data, error))
+ goto io_lose;
+
+ tempfile_fd = g_file_open_tmp ("dbus-binding-tool-c-marshallers.XXXXXX",
+ &tempfile_name, error);
+ if (tempfile_fd < 0)
+ goto io_lose;
+
+ data.channel = g_io_channel_unix_new (tempfile_fd);
+ if (!g_io_channel_set_encoding (data.channel, NULL, error))
+ goto io_lose;
+ g_hash_table_foreach (data.generated, write_marshaller, &data);
+ if (error && *error != NULL)
+ {
+ ret = FALSE;
+ g_io_channel_shutdown (data.channel, TRUE, error);
+ g_io_channel_unref (data.channel);
+ data.channel = NULL;
+ goto io_lose;
+ }
+
+ g_io_channel_shutdown (data.channel, TRUE, error);
+ g_io_channel_unref (data.channel);
+ data.channel = NULL;
+
+ /* Now spawn glib-genmarshal to insert all our required marshallers */
+ argv = g_ptr_array_new ();
+ g_ptr_array_add (argv, "glib-genmarshal");
+ g_ptr_array_add (argv, "--header");
+ g_ptr_array_add (argv, "--body");
+ g_ptr_array_add (argv, "--skip-source");
+ g_ptr_array_add (argv, g_strdup_printf ("--prefix=%s%s", MARSHAL_PREFIX, prefix));
+ g_ptr_array_add (argv, tempfile_name);
+ g_ptr_array_add (argv, NULL);
+ if (!g_spawn_async_with_pipes (NULL, (char**)argv->pdata, NULL,
+ G_SPAWN_SEARCH_PATH,
+ NULL, NULL,
+ &child_pid,
+ NULL,
+ &child_stdout, NULL, error))
+ {
+ g_ptr_array_free (argv, TRUE);
+ goto io_lose;
+ }
+ g_ptr_array_free (argv, TRUE);
+
+ genmarshal_stdout = g_io_channel_unix_new (child_stdout);
+ if (!g_io_channel_set_encoding (genmarshal_stdout, NULL, error))
+ goto io_lose;
+
+ WRITE_OR_LOSE ("/* Generated by dbus-binding-tool; do not edit! */\n\n");
+
+ while ((iostatus = g_io_channel_read_chars (genmarshal_stdout, buf, sizeof (buf),
+ &bytes_read, error)) == G_IO_STATUS_NORMAL)
+ if (g_io_channel_write_chars (channel, buf, bytes_read, &bytes_written, error) != G_IO_STATUS_NORMAL)
+ goto io_lose;
+ if (iostatus != G_IO_STATUS_EOF)
+ goto io_lose;
+
+ g_io_channel_shutdown (genmarshal_stdout, TRUE, error);
+
+ WRITE_OR_LOSE ("#include <dbus/dbus-glib.h>\n");
+
+ data.channel = channel;
+ g_io_channel_ref (data.channel);
+ if (!generate_glue_toplevel (info, &data, error))
+ goto io_lose;
+
+ ret = TRUE;
+ cleanup:
+ if (tempfile_name)
+ unlink (tempfile_name);
+ g_free (tempfile_name);
+ if (genmarshal_stdout)
+ g_io_channel_unref (genmarshal_stdout);
+ if (data.channel)
+ g_io_channel_unref (data.channel);
+ g_hash_table_destroy (data.generated);
+
+ return ret;
+ io_lose:
+ ret = FALSE;
+ goto cleanup;
+}
+
+static char *
+iface_to_c_prefix (const char *iface)
+{
+ char **components;
+ char **component;
+ GString *ret;
+ gboolean first;
+
+ components = g_strsplit (iface, ".", 0);
+
+ first = TRUE;
+ ret = g_string_new ("");
+ for (component = components; *component; component++)
+ {
+ if (!first)
+ g_string_append_c (ret, '_');
+ else
+ first = FALSE;
+ g_string_append (ret, *component);
+ }
+ g_strfreev (components);
+ return g_string_free (ret, FALSE);
+}
+
+static char *
+compute_client_method_name (const char *iface_prefix, MethodInfo *method)
+{
+ char *method_name_uscored, *ret;
+
+ method_name_uscored = _dbus_gutils_wincaps_to_uscore (method_info_get_name (method));
+ ret = g_strdup_printf ("%s_%s", iface_prefix, method_name_uscored);
+ g_free (method_name_uscored);
+
+ return ret;
+}
+
+static gboolean
+write_formal_parameters (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, GError **error)
+{
+ GSList *args;
+
+ for (args = method_info_get_args (method); args; args = args->next)
+ {
+ ArgInfo *arg;
+ const char *type_str;
+ const char *type_suffix;
+ GType gtype;
+ int direction;
+
+ arg = args->data;
+
+ WRITE_OR_LOSE (", ");
+
+ direction = arg_info_get_direction (arg);
+
+ gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+ if (gtype == G_TYPE_INVALID)
+ {
+ g_set_error (error,
+ DBUS_BINDING_TOOL_ERROR,
+ DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
+ "Unsupported conversion from D-BUS type signature \"%s\" to glib C type in method \"%s\" of interface \"%s\"",
+ arg_info_get_type (arg),
+ method_info_get_name (method),
+ interface_info_get_name (iface));
+ return FALSE;
+ }
+ type_str = dbus_g_type_get_c_name (gtype);
+ g_assert (type_str);
+ /* Variants are special...*/
+ if (gtype == G_TYPE_VALUE)
+ {
+ if (direction == ARG_IN)
+ type_suffix = "*";
+ else
+ type_suffix = "";
+ }
+ else if ((g_type_is_a (gtype, G_TYPE_BOXED)
+ || g_type_is_a (gtype, G_TYPE_OBJECT)
+ || g_type_is_a (gtype, G_TYPE_POINTER)))
+ type_suffix = "*";
+ else
+ type_suffix = "";
+
+
+ switch (direction)
+ {
+ case ARG_IN:
+ if (!write_printf_to_iochannel ("const %s%s IN_%s", channel, error,
+ type_str,
+ type_suffix,
+ arg_info_get_name (arg)))
+ goto io_lose;
+ break;
+ case ARG_OUT:
+ if (!write_printf_to_iochannel ("%s%s* OUT_%s", channel, error,
+ type_str,
+ type_suffix,
+ arg_info_get_name (arg)))
+ goto io_lose;
+ break;
+ case ARG_INVALID:
+ break;
+ }
+ }
+
+ return TRUE;
+ io_lose:
+ return FALSE;
+}
+
+#define MAP_FUNDAMENTAL(NAME) \
+ case G_TYPE_ ## NAME: \
+ return g_strdup ("G_TYPE_" #NAME);
+#define MAP_KNOWN(NAME) \
+ if (gtype == NAME) \
+ return g_strdup (#NAME)
+static char *
+dbus_g_type_get_lookup_function (GType gtype)
+{
+ char *type_lookup;
+ switch (gtype)
+ {
+ MAP_FUNDAMENTAL(CHAR);
+ MAP_FUNDAMENTAL(UCHAR);
+ MAP_FUNDAMENTAL(BOOLEAN);
+ MAP_FUNDAMENTAL(LONG);
+ MAP_FUNDAMENTAL(ULONG);
+ MAP_FUNDAMENTAL(INT);
+ MAP_FUNDAMENTAL(UINT);
+ MAP_FUNDAMENTAL(INT64);
+ MAP_FUNDAMENTAL(UINT64);
+ MAP_FUNDAMENTAL(FLOAT);
+ MAP_FUNDAMENTAL(DOUBLE);
+ MAP_FUNDAMENTAL(STRING);
+ }
+ if (dbus_g_type_is_collection (gtype))
+ {
+ GType elt_gtype;
+ char *sublookup;
+
+ elt_gtype = dbus_g_type_get_collection_specialization (gtype);
+ sublookup = dbus_g_type_get_lookup_function (elt_gtype);
+ g_assert (sublookup);
+
+ if (_dbus_g_type_is_fixed (elt_gtype))
+ {
+ type_lookup = g_strdup_printf ("dbus_g_type_get_collection "
+ "(\"GArray\", %s)", sublookup);
+ }
+ else
+ {
+ type_lookup = g_strdup_printf ("dbus_g_type_get_collection "
+ "(\"GPtrArray\", %s)", sublookup);
+ }
+
+ g_free (sublookup);
+
+ return type_lookup;
+ }
+ else if (dbus_g_type_is_map (gtype))
+ {
+ GType key_gtype;
+ char *key_lookup;
+ GType value_gtype;
+ char *value_lookup;
+
+ key_gtype = dbus_g_type_get_map_key_specialization (gtype);
+ value_gtype = dbus_g_type_get_map_value_specialization (gtype);
+ key_lookup = dbus_g_type_get_lookup_function (key_gtype);
+ g_assert (key_lookup);
+ value_lookup = dbus_g_type_get_lookup_function (value_gtype);
+ g_assert (value_lookup);
+ type_lookup = g_strdup_printf ("dbus_g_type_get_map (\"GHashTable\", %s, %s)",
+ key_lookup, value_lookup);
+ g_free (key_lookup);
+ 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_ARRAY);
+ MAP_KNOWN(DBUS_TYPE_G_PROXY);
+ MAP_KNOWN(DBUS_TYPE_G_OBJECT_PATH);
+ MAP_KNOWN(DBUS_TYPE_G_SIGNATURE);
+ return NULL;
+}
+#undef MAP_FUNDAMENTAL
+#undef MAP_KNOWN
+
+static gboolean
+write_args_for_direction (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, int direction, GError **error)
+{
+ GSList *args;
+ char *type_lookup = NULL;
+
+ for (args = method_info_get_args (method); args; args = args->next)
+ {
+ ArgInfo *arg;
+ GType gtype;
+
+ arg = args->data;
+
+ if (direction != arg_info_get_direction (arg))
+ continue;
+
+ gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+ g_assert (gtype != G_TYPE_INVALID);
+ type_lookup = dbus_g_type_get_lookup_function (gtype);
+ g_assert (type_lookup != NULL);
+
+ switch (direction)
+ {
+
+ case ARG_IN:
+ if (!write_printf_to_iochannel ("%s, IN_%s, ", channel, error,
+ type_lookup,
+ arg_info_get_name (arg)))
+ goto io_lose;
+ break;
+ case ARG_OUT:
+ if (!write_printf_to_iochannel ("%s, OUT_%s, ", channel, error,
+ type_lookup,
+ arg_info_get_name (arg)))
+ goto io_lose;
+ break;
+ case ARG_INVALID:
+ break;
+ }
+ g_free (type_lookup);
+ }
+
+ return TRUE;
+ io_lose:
+ g_free (type_lookup);
+ return FALSE;
+}
+
+static gboolean
+check_supported_parameters (MethodInfo *method)
+{
+ GSList *args;
+
+ for (args = method_info_get_args (method); args; args = args->next)
+ {
+ ArgInfo *arg;
+ GType gtype;
+
+ arg = args->data;
+ gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+ if (gtype == G_TYPE_INVALID)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+write_untyped_out_args (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, GError **error)
+{
+ GSList *args;
+
+ for (args = method_info_get_args (method); args; args = args->next)
+ {
+ ArgInfo *arg;
+
+ arg = args->data;
+ if (arg_info_get_direction (arg) != ARG_OUT)
+ continue;
+
+ if (!write_printf_to_iochannel ("OUT_%s, ", channel, error,
+ arg_info_get_name (arg)))
+ goto io_lose;
+ }
+
+ return TRUE;
+ io_lose:
+ return FALSE;
+}
+
+static gboolean
+write_formal_declarations_for_direction (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, const int direction, GError **error)
+ {
+ GSList *args;
+
+ for (args = method_info_get_args (method); args; args = args->next)
+ {
+ ArgInfo *arg;
+ GType gtype;
+ const char *type_str, *type_suffix, *type_initializer = "";
+ int dir;
+
+ arg = args->data;
+
+ dir = arg_info_get_direction (arg);
+
+ gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+ type_str = dbus_g_type_get_c_name (gtype);
+
+ if (!type_str)
+ {
+ g_set_error (error,
+ DBUS_BINDING_TOOL_ERROR,
+ DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
+ "Unsupported conversion from D-BUS type signature \"%s\" to glib C type in method \"%s\" of interface \"%s\"",
+ arg_info_get_type (arg),
+ method_info_get_name (method),
+ interface_info_get_name (iface));
+ return FALSE;
+ }
+
+ /* Variants are special...*/
+ if (gtype == G_TYPE_VALUE)
+ {
+ if (direction == ARG_IN)
+ type_suffix = "*";
+ else
+ {
+ type_suffix = "";
+ type_initializer = " = { 0, }";
+ }
+ }
+ else if ((g_type_is_a (gtype, G_TYPE_BOXED)
+ || g_type_is_a (gtype, G_TYPE_OBJECT)
+ || g_type_is_a (gtype, G_TYPE_POINTER)))
+ type_suffix = "*";
+ else
+ type_suffix = "";
+
+ if (direction != dir)
+ continue;
+
+ switch (dir)
+ {
+ case ARG_IN:
+ if (!write_printf_to_iochannel (" %s%s IN_%s;\n", channel, error,
+ type_str, type_suffix,
+ arg_info_get_name (arg)))
+ goto io_lose;
+ break;
+ case ARG_OUT:
+ if (!write_printf_to_iochannel (" %s%s OUT_%s%s;\n", channel, error,
+ type_str, type_suffix,
+ arg_info_get_name (arg),
+ type_initializer))
+ goto io_lose;
+ break;
+ case ARG_INVALID:
+ break;
+ }
+ }
+ return TRUE;
+ io_lose:
+ return FALSE;
+ }
+
+static gboolean
+write_formal_parameters_for_direction (InterfaceInfo *iface, MethodInfo *method, int dir, GIOChannel *channel, GError **error)
+{
+ GSList *args;
+
+ for (args = method_info_get_args (method); args; args = args->next)
+ {
+ ArgInfo *arg;
+ const char *type_str;
+ const char *type_suffix;
+ GType gtype;
+ int direction;
+
+ arg = args->data;
+
+ direction = arg_info_get_direction (arg);
+ if (dir != direction) continue;
+
+ WRITE_OR_LOSE (", ");
+
+ gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+ type_str = dbus_g_type_get_c_name (gtype);
+ /* Variants are special...*/
+ if (gtype == G_TYPE_VALUE)
+ {
+ if (direction == ARG_IN)
+ type_suffix = "*";
+ else
+ type_suffix = "";
+ }
+ else if ((g_type_is_a (gtype, G_TYPE_BOXED)
+ || g_type_is_a (gtype, G_TYPE_OBJECT)
+ || g_type_is_a (gtype, G_TYPE_POINTER)))
+ type_suffix = "*";
+ else
+ type_suffix = "";
+
+ if (!type_str)
+ {
+ g_set_error (error,
+ DBUS_BINDING_TOOL_ERROR,
+ DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
+ "Unsupported conversion from D-BUS type signature \"%s\" to glib C type in method \"%s\" of interface \"%s\"",
+ arg_info_get_type (arg),
+ method_info_get_name (method),
+ interface_info_get_name (iface));
+ return FALSE;
+ }
+
+ switch (direction)
+ {
+ case ARG_IN:
+ if (!write_printf_to_iochannel ("const %s%s IN_%s", channel, error,
+ type_str,
+ type_suffix,
+ arg_info_get_name (arg)))
+ goto io_lose;
+ break;
+ case ARG_OUT:
+ if (!write_printf_to_iochannel ("%s%s* OUT_%s", channel, error,
+ type_str,
+ type_suffix,
+ arg_info_get_name (arg)))
+ goto io_lose;
+ break;
+ case ARG_INVALID:
+ break;
+ }
+ }
+ return TRUE;
+ io_lose:
+ return FALSE;
+}
+
+static gboolean
+write_typed_args_for_direction (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, const int direction, GError **error)
+{
+ GSList *args;
+ char *type_lookup = NULL;
+
+ for (args = method_info_get_args (method); args; args = args->next)
+ {
+ ArgInfo *arg;
+ int dir;
+ GType gtype;
+
+ arg = args->data;
+
+ dir = arg_info_get_direction (arg);
+
+ if (dir != direction)
+ continue;
+
+ gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+ type_lookup = dbus_g_type_get_lookup_function (gtype);
+
+ if (!write_printf_to_iochannel ("%s, &%s_%s, ", channel, error, type_lookup, direction == ARG_IN ? "IN" : "OUT", arg_info_get_name (arg)))
+ goto io_lose;
+ g_free (type_lookup);
+ }
+ return TRUE;
+ io_lose:
+ g_free (type_lookup);
+ return FALSE;
+}
+
+static gboolean
+write_async_method_client (GIOChannel *channel, InterfaceInfo *interface, MethodInfo *method, GError **error)
+{
+ char *method_name, *iface_prefix;
+ const char *interface_c_name;
+
+ iface_prefix = iface_to_c_prefix (interface_info_get_name (interface));
+ interface_c_name = interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_CLIENT_C_SYMBOL);
+ if (interface_c_name == NULL)
+ {
+ interface_c_name = (const char *) iface_prefix;
+ }
+
+ method_name = g_strdup (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_CLIENT_C_SYMBOL));
+ if (method_name == NULL)
+ {
+ method_name = compute_client_method_name (interface_c_name, method);
+ }
+ g_free(iface_prefix);
+
+ /* Write the typedef for the client callback */
+ if (!write_printf_to_iochannel ("typedef void (*%s_reply) (DBusGProxy *proxy, ", channel, error, method_name))
+ goto io_lose;
+ {
+ GSList *args;
+ for (args = method_info_get_args (method); args; args = args->next)
+ {
+ ArgInfo *arg;
+ const char *type_suffix, *type_str;
+ GType gtype;
+
+ arg = args->data;
+
+ if (arg_info_get_direction (arg) != ARG_OUT)
+ continue;
+ gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+ if (gtype != G_TYPE_VALUE && (g_type_is_a (gtype, G_TYPE_BOXED)
+ || g_type_is_a (gtype, G_TYPE_OBJECT)
+ || g_type_is_a (gtype, G_TYPE_POINTER)))
+ type_suffix = "*";
+ else
+ type_suffix = "";
+ type_str = dbus_g_type_get_c_name (_dbus_gtype_from_signature (arg_info_get_type (arg), TRUE));
+ if (!write_printf_to_iochannel ("%s %sOUT_%s, ", channel, error, type_str, type_suffix, arg_info_get_name (arg)))
+ goto io_lose;
+ }
+ }
+ WRITE_OR_LOSE ("GError *error, gpointer userdata);\n\n");
+
+
+ /* Write the callback when the call returns */
+ WRITE_OR_LOSE ("static void\n");
+ if (!write_printf_to_iochannel ("%s_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data)\n", channel, error, method_name))
+ goto io_lose;
+ WRITE_OR_LOSE ("{\n");
+ WRITE_OR_LOSE (" DBusGAsyncData *data = (DBusGAsyncData*) user_data;\n GError *error = NULL;\n");
+ if (!write_formal_declarations_for_direction (interface, method, channel, ARG_OUT, error))
+ goto io_lose;
+ /* TODO: handle return boolean of end_call */
+ WRITE_OR_LOSE (" dbus_g_proxy_end_call (proxy, call, &error, ");
+ if (!write_typed_args_for_direction (interface, method, channel, ARG_OUT, error))
+ goto io_lose;
+ WRITE_OR_LOSE("G_TYPE_INVALID);\n");
+ if (!write_printf_to_iochannel (" (*(%s_reply)data->cb) (proxy, ", channel, error, method_name))
+ goto io_lose;
+ if (!write_untyped_out_args (interface, method, channel, error))
+ goto io_lose;
+ WRITE_OR_LOSE ("error, data->userdata);\n");
+ WRITE_OR_LOSE (" return;\n}\n\n");
+
+
+ /* Write the main wrapper function */
+ WRITE_OR_LOSE ("static inline DBusGProxyCall*\n");
+ if (!write_printf_to_iochannel ("%s_async (DBusGProxy *proxy", channel, error,
+ method_name))
+ goto io_lose;
+ if (!write_formal_parameters_for_direction (interface, method, ARG_IN, channel, error))
+ goto io_lose;
+
+ if (!write_printf_to_iochannel (", %s_reply callback, gpointer userdata)\n\n", channel, error, method_name))
+ goto io_lose;
+
+ WRITE_OR_LOSE ("{\n");
+ WRITE_OR_LOSE (" DBusGAsyncData *stuff;\n stuff = g_slice_new (DBusGAsyncData);\n stuff->cb = G_CALLBACK (callback);\n stuff->userdata = userdata;\n");
+ if (!write_printf_to_iochannel (" return dbus_g_proxy_begin_call (proxy, \"%s\", %s_async_callback, stuff, _dbus_glib_async_data_free, ", channel, error, method_info_get_name (method), method_name))
+ goto io_lose;
+ if (!write_args_for_direction (interface, method, channel, ARG_IN, error))
+ goto io_lose;
+ WRITE_OR_LOSE ("G_TYPE_INVALID);\n}\n");
+
+ g_free (method_name);
+ return TRUE;
+ io_lose:
+ g_free (method_name);
+ return FALSE;
+ }
+
+static gboolean
+generate_client_glue_list (GSList *list, DBusBindingToolCData *data, GError **error)
+{
+ GSList *tmp;
+
+ tmp = list;
+ while (tmp != NULL)
+ {
+ if (!generate_client_glue (tmp->data, data, error))
+ return FALSE;
+ tmp = tmp->next;
+ }
+ return TRUE;
+}
+
+static gboolean
+generate_client_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
+{
+ char *iface_prefix;
+ char *method_c_name;
+ iface_prefix = NULL;
+ method_c_name = NULL;
+
+ if (base_info_get_type (base) == INFO_TYPE_NODE)
+ {
+ if (!generate_client_glue_list (node_info_get_nodes ((NodeInfo *) base),
+ data, error))
+ return FALSE;
+ if (!generate_client_glue_list (node_info_get_interfaces ((NodeInfo *) base),
+ data, error))
+ return FALSE;
+ }
+ else
+ {
+ GIOChannel *channel;
+ InterfaceInfo *interface;
+ GSList *methods;
+ GSList *tmp;
+ const char *interface_c_name;
+
+ channel = data->channel;
+
+ interface = (InterfaceInfo *) base;
+
+ methods = interface_info_get_methods (interface);
+
+ iface_prefix = iface_to_c_prefix (interface_info_get_name (interface));
+ interface_c_name = interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_CLIENT_C_SYMBOL);
+ if (interface_c_name == NULL)
+ {
+ interface_c_name = (const char *) iface_prefix;
+ }
+
+ if (!write_printf_to_iochannel ("#ifndef DBUS_GLIB_CLIENT_WRAPPERS_%s\n"
+ "#define DBUS_GLIB_CLIENT_WRAPPERS_%s\n\n",
+ channel, error,
+ iface_prefix, iface_prefix))
+ goto io_lose;
+
+ for (tmp = methods; tmp != NULL; tmp = g_slist_next (tmp))
+ {
+ MethodInfo *method;
+ gboolean is_noreply;
+
+ method = (MethodInfo *) tmp->data;
+ method_c_name = g_strdup (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_CLIENT_C_SYMBOL));
+ if (method_c_name == NULL)
+ {
+ method_c_name = compute_client_method_name (interface_c_name, method);
+ }
+
+ is_noreply = method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_NOREPLY) != NULL;
+
+ if (data->ignore_unsupported && !check_supported_parameters (method))
+ {
+ g_warning ("Ignoring unsupported signature in method \"%s\" of interface \"%s\"\n",
+ method_info_get_name (method),
+ interface_info_get_name (interface));
+ g_free (method_c_name);
+ method_c_name = NULL;
+ continue;
+ }
+
+
+ WRITE_OR_LOSE ("static inline gboolean\n");
+ if (!write_printf_to_iochannel ("%s (DBusGProxy *proxy", channel, error,
+ method_c_name))
+ goto io_lose;
+ g_free (method_c_name);
+ method_c_name = NULL;
+
+ if (!write_formal_parameters (interface, method, channel, error))
+ goto io_lose;
+
+ WRITE_OR_LOSE (", GError **error)\n\n");
+
+ WRITE_OR_LOSE ("{\n");
+
+ if (is_noreply) {
+ if (!write_printf_to_iochannel (" dbus_g_proxy_call_no_reply (proxy, \"%s\", ", channel, error,
+ method_info_get_name (method)))
+ goto io_lose;
+
+ if (!write_args_for_direction (interface, method, channel, ARG_IN, error))
+ goto io_lose;
+
+ WRITE_OR_LOSE ("G_TYPE_INVALID, ");
+
+ if (!write_args_for_direction (interface, method, channel, ARG_OUT, error))
+ goto io_lose;
+
+ WRITE_OR_LOSE ("G_TYPE_INVALID);\n");
+
+ WRITE_OR_LOSE (" return TRUE;\n}\n\n");
+ } else {
+ if (!write_printf_to_iochannel (" return dbus_g_proxy_call (proxy, \"%s\", ", channel, error,
+ method_info_get_name (method)))
+ goto io_lose;
+
+ WRITE_OR_LOSE ("error, ");
+
+ if (!write_args_for_direction (interface, method, channel, ARG_IN, error))
+ goto io_lose;
+
+ WRITE_OR_LOSE ("G_TYPE_INVALID, ");
+
+ if (!write_args_for_direction (interface, method, channel, ARG_OUT, error))
+ goto io_lose;
+
+ WRITE_OR_LOSE ("G_TYPE_INVALID);\n}\n\n");
+ }
+
+ write_async_method_client (channel, interface, method, error);
+ }
+
+ if (!write_printf_to_iochannel ("#endif /* defined DBUS_GLIB_CLIENT_WRAPPERS_%s */\n\n", channel, error, iface_prefix))
+ goto io_lose;
+
+ g_free (iface_prefix);
+ }
+ return TRUE;
+ io_lose:
+ g_free (method_c_name);
+ g_free (iface_prefix);
+ return FALSE;
+}
+
+
+gboolean
+dbus_binding_tool_output_glib_client (BaseInfo *info, GIOChannel *channel, gboolean ignore_unsupported, GError **error)
+{
+ DBusBindingToolCData data;
+ gboolean ret;
+
+ memset (&data, 0, sizeof (data));
+
+ data.channel = channel;
+ data.ignore_unsupported = ignore_unsupported;
+
+ dbus_g_type_specialized_init ();
+ _dbus_g_type_specialized_builtins_init ();
+
+ WRITE_OR_LOSE ("/* Generated by dbus-binding-tool; do not edit! */\n\n");
+ WRITE_OR_LOSE ("#include <glib.h>\n");
+ WRITE_OR_LOSE ("#include <dbus/dbus-glib.h>\n\n");
+ WRITE_OR_LOSE ("G_BEGIN_DECLS\n\n");
+
+ WRITE_OR_LOSE ("#ifndef _DBUS_GLIB_ASYNC_DATA_FREE\n");
+ WRITE_OR_LOSE ("#define _DBUS_GLIB_ASYNC_DATA_FREE\n");
+ WRITE_OR_LOSE ("static inline void\n");
+ WRITE_OR_LOSE ("_dbus_glib_async_data_free (gpointer stuff)\n{\n\tg_slice_free (DBusGAsyncData, stuff);\n}\n");
+ WRITE_OR_LOSE ("#endif\n\n");
+
+ ret = generate_client_glue (info, &data, error);
+ if (!ret)
+ goto io_lose;
+
+ WRITE_OR_LOSE ("G_END_DECLS\n");
+
+ return ret;
+ io_lose:
+ return FALSE;
+}
Index: dbus-glib-0.112-new/dbus/dbus-gvalue-utils.c
===================================================================
--- dbus-glib-0.112-new/dbus/dbus-gvalue-utils.c (nonexistent)
+++ dbus-glib-0.112-new/dbus/dbus-gvalue-utils.c (revision 5)
@@ -0,0 +1,1372 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-gvalue-utils.c: Non-DBus-specific functions related to GType/GValue
+ *
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <config.h>
+#include "dbus/dbus-glib.h"
+#include "dbus-gtype-specialized-priv.h"
+#include "dbus-gvalue-utils.h"
+#include "dbus-gtest.h"
+#include <glib.h>
+#include <string.h>
+#include <gobject/gvaluecollector.h>
+
+
+static guint
+fixed_type_get_size (GType type)
+{
+ switch (type)
+ {
+ case G_TYPE_CHAR:
+ case G_TYPE_UCHAR:
+ return sizeof (gchar);
+ case G_TYPE_BOOLEAN:
+ return sizeof (gboolean);
+ case G_TYPE_LONG:
+ case G_TYPE_ULONG:
+ return sizeof (glong);
+ case G_TYPE_INT:
+ case G_TYPE_UINT:
+ return sizeof (gint);
+ case G_TYPE_INT64:
+ case G_TYPE_UINT64:
+ return sizeof (gint64);
+ case G_TYPE_FLOAT:
+ return sizeof (gfloat);
+ case G_TYPE_DOUBLE:
+ return sizeof (gdouble);
+ default:
+ return 0;
+ }
+}
+
+gboolean
+_dbus_g_type_is_fixed (GType type)
+{
+ return fixed_type_get_size (type) > 0;
+}
+
+guint
+_dbus_g_type_fixed_get_size (GType type)
+{
+ g_assert (_dbus_g_type_is_fixed (type));
+ return fixed_type_get_size (type);
+}
+
+gboolean
+_dbus_gvalue_store (GValue *value,
+ gpointer storage)
+{
+ /* FIXME - can we use the GValue lcopy_value method
+ * to do this in a cleaner way?
+ */
+ switch (g_type_fundamental (G_VALUE_TYPE (value)))
+ {
+ case G_TYPE_CHAR:
+ *((gchar *) storage) = g_value_get_char (value);
+ return TRUE;
+ case G_TYPE_UCHAR:
+ *((guchar *) storage) = g_value_get_uchar (value);
+ return TRUE;
+ case G_TYPE_BOOLEAN:
+ *((gboolean *) storage) = g_value_get_boolean (value);
+ return TRUE;
+ case G_TYPE_LONG:
+ *((glong *) storage) = g_value_get_long (value);
+ return TRUE;
+ case G_TYPE_ULONG:
+ *((gulong *) storage) = g_value_get_ulong (value);
+ return TRUE;
+ case G_TYPE_INT:
+ *((gint *) storage) = g_value_get_int (value);
+ return TRUE;
+ case G_TYPE_UINT:
+ *((guint *) storage) = g_value_get_uint (value);
+ return TRUE;
+ case G_TYPE_INT64:
+ *((gint64 *) storage) = g_value_get_int64 (value);
+ return TRUE;
+ case G_TYPE_UINT64:
+ *((guint64 *) storage) = g_value_get_uint64 (value);
+ return TRUE;
+ case G_TYPE_DOUBLE:
+ *((gdouble *) storage) = g_value_get_double (value);
+ return TRUE;
+ case G_TYPE_STRING:
+ *((gchar **) storage) = (char*) g_value_get_string (value);
+ return TRUE;
+ case G_TYPE_OBJECT:
+ *((gpointer *) storage) = g_value_get_object (value);
+ return TRUE;
+ case G_TYPE_BOXED:
+ *((gpointer *) storage) = g_value_get_boxed (value);
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+gboolean
+_dbus_gvalue_set_from_pointer (GValue *value,
+ gconstpointer storage)
+{
+ /* FIXME - is there a better way to do this? */
+ switch (g_type_fundamental (G_VALUE_TYPE (value)))
+ {
+ case G_TYPE_CHAR:
+ g_value_set_char (value, *((gchar *) storage));
+ return TRUE;
+ case G_TYPE_UCHAR:
+ g_value_set_uchar (value, *((guchar *) storage));
+ return TRUE;
+ case G_TYPE_BOOLEAN:
+ g_value_set_boolean (value, *((gboolean *) storage));
+ return TRUE;
+ case G_TYPE_LONG:
+ g_value_set_long (value, *((glong *) storage));
+ return TRUE;
+ case G_TYPE_ULONG:
+ g_value_set_ulong (value, *((gulong *) storage));
+ return TRUE;
+ case G_TYPE_INT:
+ g_value_set_int (value, *((gint *) storage));
+ return TRUE;
+ case G_TYPE_UINT:
+ g_value_set_uint (value, *((guint *) storage));
+ return TRUE;
+ case G_TYPE_INT64:
+ g_value_set_int64 (value, *((gint64 *) storage));
+ return TRUE;
+ case G_TYPE_UINT64:
+ g_value_set_uint64 (value, *((guint64 *) storage));
+ return TRUE;
+ case G_TYPE_DOUBLE:
+ g_value_set_double (value, *((gdouble *) storage));
+ return TRUE;
+ case G_TYPE_STRING:
+ g_value_set_string (value, *((gchar **) storage));
+ return TRUE;
+ case G_TYPE_OBJECT:
+ g_value_set_object (value, *((gpointer *) storage));
+ return TRUE;
+ case G_TYPE_BOXED:
+ g_value_set_boxed (value, *((gpointer *) storage));
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+gboolean
+_dbus_gvalue_take (GValue *value,
+ GTypeCValue *cvalue)
+{
+ GType g_type;
+ GTypeValueTable *value_table;
+ char *error_msg;
+
+ g_type = G_VALUE_TYPE (value);
+ value_table = g_type_value_table_peek (g_type);
+
+ error_msg = value_table->collect_value (value, 1, cvalue, G_VALUE_NOCOPY_CONTENTS);
+ if (error_msg)
+ {
+ g_warning ("%s: %s", G_STRLOC, error_msg);
+ g_free (error_msg);
+ return FALSE;
+ }
+ /* Clear the NOCOPY_CONTENTS flag; we want to take ownership
+ * of the value.
+ */
+ value->data[1].v_uint &= ~(G_VALUE_NOCOPY_CONTENTS);
+ return TRUE;
+}
+
+gboolean
+_dbus_gtype_can_signal_error (GType gtype)
+{
+ switch (gtype)
+ {
+ case G_TYPE_BOOLEAN:
+ case G_TYPE_INT:
+ case G_TYPE_UINT:
+ case G_TYPE_STRING:
+ case G_TYPE_BOXED:
+ case G_TYPE_OBJECT:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+gboolean
+_dbus_gvalue_signals_error (const GValue *value)
+{
+ /* Hardcoded rules for return value semantics for certain
+ * types. Perhaps in the future we'd want an annotation
+ * specifying which return values are errors, but in
+ * reality people will probably just use boolean and
+ * boxed, and there the semantics are pretty standard.
+ */
+ switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)))
+ {
+ case G_TYPE_BOOLEAN:
+ return (g_value_get_boolean (value) == FALSE);
+ break;
+ case G_TYPE_INT:
+ return (g_value_get_int (value) < 0);
+ break;
+ case G_TYPE_UINT:
+ return (g_value_get_uint (value) == 0);
+ break;
+ case G_TYPE_STRING:
+ return (g_value_get_string (value) == NULL);
+ break;
+ case G_TYPE_BOXED:
+ return (g_value_get_boxed (value) == NULL);
+ break;
+ case G_TYPE_OBJECT:
+ return (g_value_get_object (value) == NULL);
+ break;
+ default:
+ g_assert_not_reached ();
+ return FALSE;
+ }
+}
+
+
+static gboolean
+hash_func_from_gtype (GType gtype, GHashFunc *func)
+{
+ switch (gtype)
+ {
+ case G_TYPE_CHAR:
+ case G_TYPE_UCHAR:
+ case G_TYPE_BOOLEAN:
+ case G_TYPE_INT:
+ case G_TYPE_UINT:
+ *func = NULL;
+ return TRUE;
+ case G_TYPE_STRING:
+ *func = g_str_hash;
+ return TRUE;
+ default:
+ if (gtype == DBUS_TYPE_G_OBJECT_PATH)
+ {
+ *func = g_str_hash;
+ return TRUE;
+ }
+ else if (gtype == DBUS_TYPE_G_SIGNATURE)
+ {
+ *func = g_str_hash;
+ return TRUE;
+ }
+ return FALSE;
+ }
+}
+
+static void
+unset_and_free_g_value (gpointer val)
+{
+ GValue *value = val;
+
+ g_value_unset (value);
+ g_free (value);
+}
+
+static gboolean
+gtype_can_simple_free (GType type);
+
+static gboolean
+hash_simple_free_from_gtype (GType gtype, GDestroyNotify *func)
+{
+ switch (gtype)
+ {
+ case G_TYPE_CHAR:
+ case G_TYPE_UCHAR:
+ case G_TYPE_BOOLEAN:
+ case G_TYPE_INT:
+ case G_TYPE_UINT:
+ *func = NULL;
+ return TRUE;
+ case G_TYPE_DOUBLE:
+ case G_TYPE_STRING:
+ *func = g_free;
+ return TRUE;
+ default:
+ if (gtype == G_TYPE_VALUE)
+ {
+ *func = unset_and_free_g_value;
+ return TRUE;
+ }
+ else if (gtype == G_TYPE_ARRAY)
+ {
+ *func = (GDestroyNotify) g_value_array_free;
+ return TRUE;
+ }
+ else if (gtype == G_TYPE_STRV)
+ {
+ *func = (GDestroyNotify) g_strfreev;
+ return TRUE;
+ }
+ else if (gtype == DBUS_TYPE_G_OBJECT_PATH)
+ {
+ *func = g_free;
+ return TRUE;
+ }
+ else if (gtype == DBUS_TYPE_G_SIGNATURE)
+ {
+ *func = g_free;
+ return TRUE;
+ }
+ else if (dbus_g_type_is_collection (gtype))
+ {
+ const DBusGTypeSpecializedCollectionVtable* vtable;
+ vtable = dbus_g_type_collection_peek_vtable (gtype);
+ if (vtable->base_vtable.simple_free_func)
+ {
+ *func = vtable->base_vtable.simple_free_func;
+ return TRUE;
+ }
+ }
+ else if (dbus_g_type_is_map (gtype))
+ {
+ const DBusGTypeSpecializedMapVtable* vtable;
+ GType key_gtype, value_gtype;
+
+ key_gtype = dbus_g_type_get_map_key_specialization (gtype);
+ value_gtype = dbus_g_type_get_map_value_specialization (gtype);
+
+ /* if either the key or the value don't have "simple" (without a
+ * GType) free functions, then the hashtable's contents must be freed
+ * with hashtable_free, so the hashtable itself can't have a simple
+ * free function. */
+ if (!gtype_can_simple_free (key_gtype) ||
+ !gtype_can_simple_free (value_gtype))
+ return FALSE;
+
+ vtable = dbus_g_type_map_peek_vtable (gtype);
+ if (vtable->base_vtable.simple_free_func)
+ {
+ *func = vtable->base_vtable.simple_free_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;
+ }
+}
+
+static gboolean
+gtype_can_simple_free (GType type)
+{
+ GDestroyNotify func;
+ return hash_simple_free_from_gtype (type, &func);
+}
+
+gboolean
+_dbus_gtype_is_valid_hash_key (GType type)
+{
+ GHashFunc func;
+ return hash_func_from_gtype (type, &func);
+}
+
+gboolean
+_dbus_gtype_is_valid_hash_value (GType gtype)
+{
+ /* anything we can take into a GValue using gvalue_take_hash_value is fine */
+ switch (g_type_fundamental (gtype))
+ {
+ case G_TYPE_CHAR:
+ case G_TYPE_UCHAR:
+ case G_TYPE_BOOLEAN:
+ case G_TYPE_INT:
+ case G_TYPE_UINT:
+ case G_TYPE_DOUBLE:
+ case G_TYPE_STRING:
+ case G_TYPE_BOXED:
+ case G_TYPE_OBJECT:
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+GHashFunc
+_dbus_g_hash_func_from_gtype (GType gtype)
+{
+ GHashFunc func;
+ gboolean ret;
+ ret = hash_func_from_gtype (gtype, &func);
+ g_assert (ret != FALSE);
+ return func;
+}
+
+GEqualFunc
+_dbus_g_hash_equal_from_gtype (GType gtype)
+{
+ g_assert (_dbus_gtype_is_valid_hash_key (gtype));
+
+ switch (gtype)
+ {
+ case G_TYPE_CHAR:
+ case G_TYPE_UCHAR:
+ case G_TYPE_BOOLEAN:
+ case G_TYPE_INT:
+ case G_TYPE_UINT:
+ return NULL;
+ case G_TYPE_STRING:
+ return g_str_equal;
+ default:
+ if (gtype == DBUS_TYPE_G_OBJECT_PATH)
+ return g_str_equal;
+ else if (gtype == DBUS_TYPE_G_SIGNATURE)
+ return g_str_equal;
+ g_assert_not_reached ();
+ return NULL;
+ }
+}
+
+static void
+hash_fake_simple_free_func (gpointer val)
+{
+ /* Havoc would be proud... :P */
+ g_critical ("If you see this message then the author of this application or "
+ "one of its libraries has tried to remove or replace the value %p in a "
+ "hash table which was constructed by the D-Bus Glib bindings.\n\n"
+
+ "However, it was not possible for the bindings to provide a destroy "
+ "function to g_hash_table_new_full which is able to free this value, as "
+ "its GType must be known in order to free it. This means the memory "
+ "allocated to store the value has most likely just been leaked.\n\n"
+
+ "To avoid this error, the GHashTable (or keys/values \"stolen\" from "
+ "it) should be freed by using g_boxed_free as follows:\n"
+ " g_boxed_free (dbus_g_type_get_map (\"GHashTable\", key_gtype, "
+ "value_gtype), hash_table);\n", val);
+}
+
+GDestroyNotify
+_dbus_g_hash_free_from_gtype (GType gtype)
+{
+ GDestroyNotify func;
+ gboolean ret;
+
+ ret = hash_simple_free_from_gtype (gtype, &func);
+
+ /* if the value doesn't have a simple free function, we cannot define a
+ * meaningful free function here. instead, this hash table must be freed
+ * using g_boxed_free so that the hash_free function gets invoked. if the
+ * user does not do so, we provide a fake free function to provide a warning
+ * in this case. */
+ if (ret == FALSE)
+ {
+ g_assert (_dbus_gtype_is_valid_hash_value (gtype));
+
+ func = hash_fake_simple_free_func;
+ }
+
+ return func;
+}
+
+static void gvalue_take_ptrarray_value (GValue *value, gpointer instance);
+
+static void
+gvalue_take_hash_value (GValue *value, gpointer instance)
+{
+ switch (g_type_fundamental (G_VALUE_TYPE (value)))
+ {
+ case G_TYPE_CHAR:
+ g_value_set_char (value, (gchar) GPOINTER_TO_INT (instance));
+ break;
+ case G_TYPE_UCHAR:
+ g_value_set_uchar (value, (guchar) GPOINTER_TO_UINT (instance));
+ break;
+ case G_TYPE_BOOLEAN:
+ g_value_set_boolean (value, (gboolean) GPOINTER_TO_UINT (instance));
+ break;
+ case G_TYPE_INT:
+ g_value_set_int (value, GPOINTER_TO_INT (instance));
+ break;
+ case G_TYPE_UINT:
+ g_value_set_uint (value, GPOINTER_TO_UINT (instance));
+ break;
+ case G_TYPE_DOUBLE:
+ g_value_set_double (value, *(gdouble *) instance);
+ break;
+ default:
+ gvalue_take_ptrarray_value (value, instance);
+ break;
+ }
+}
+
+static gpointer ptrarray_value_from_gvalue (const GValue *value);
+
+static gpointer
+hash_value_from_gvalue (GValue *value)
+{
+ switch (g_type_fundamental (G_VALUE_TYPE (value)))
+ {
+ case G_TYPE_CHAR:
+ return GINT_TO_POINTER ((int) g_value_get_char (value));
+ break;
+ case G_TYPE_UCHAR:
+ return GUINT_TO_POINTER ((guint) g_value_get_uchar (value));
+ break;
+ case G_TYPE_BOOLEAN:
+ return GUINT_TO_POINTER ((guint) g_value_get_boolean (value));
+ break;
+ case G_TYPE_INT:
+ return GINT_TO_POINTER (g_value_get_int (value));
+ break;
+ case G_TYPE_UINT:
+ return GUINT_TO_POINTER (g_value_get_uint (value));
+ break;
+ case G_TYPE_DOUBLE:
+ {
+ gdouble *p = (gdouble *) g_malloc0 (sizeof (gdouble));
+ *p = g_value_get_double (value);
+ return (gpointer) p;
+ }
+ break;
+ default:
+ return ptrarray_value_from_gvalue (value);
+ break;
+ }
+}
+
+struct DBusGHashTableValueForeachData
+{
+ DBusGTypeSpecializedMapIterator func;
+ GType key_type;
+ GType value_type;
+ gpointer data;
+};
+
+static void
+hashtable_foreach_with_values (gpointer key, gpointer value, gpointer user_data)
+{
+ GValue key_val = {0, };
+ GValue value_val = {0, };
+ struct DBusGHashTableValueForeachData *data = user_data;
+
+ g_value_init (&key_val, data->key_type);
+ g_value_init (&value_val, data->value_type);
+ gvalue_take_hash_value (&key_val, key);
+ gvalue_take_hash_value (&value_val, value);
+
+ data->func (&key_val, &value_val, data->data);
+}
+
+
+static void
+hashtable_iterator (GType hash_type,
+ gpointer instance,
+ DBusGTypeSpecializedMapIterator iterator,
+ gpointer user_data)
+{
+ struct DBusGHashTableValueForeachData data;
+ GType key_gtype;
+ GType value_gtype;
+
+ key_gtype = dbus_g_type_get_map_key_specialization (hash_type);
+ value_gtype = dbus_g_type_get_map_value_specialization (hash_type);
+
+ data.func = iterator;
+ data.key_type = key_gtype;
+ data.value_type = value_gtype;
+ data.data = user_data;
+
+ g_hash_table_foreach (instance, hashtable_foreach_with_values, &data);
+}
+
+void
+_dbus_g_hash_table_insert_steal_values (GHashTable *table,
+ GValue *key_val,
+ GValue *value_val)
+{
+ gpointer key, val;
+
+ key = hash_value_from_gvalue (key_val);
+ val = hash_value_from_gvalue (value_val);
+
+ g_hash_table_insert (table, key, val);
+}
+
+static void
+hashtable_append (DBusGTypeSpecializedAppendContext *ctx,
+ GValue *key,
+ GValue *val)
+{
+ GHashTable *table;
+
+ table = g_value_get_boxed (ctx->val);
+ _dbus_g_hash_table_insert_steal_values (table, key, val);
+}
+
+static gpointer
+hashtable_constructor (GType type)
+{
+ GHashTable *ret;
+ GType key_gtype;
+ GType value_gtype;
+
+ key_gtype = dbus_g_type_get_map_key_specialization (type);
+ value_gtype = dbus_g_type_get_map_value_specialization (type);
+
+ ret = g_hash_table_new_full (_dbus_g_hash_func_from_gtype (key_gtype),
+ _dbus_g_hash_equal_from_gtype (key_gtype),
+ _dbus_g_hash_free_from_gtype (key_gtype),
+ _dbus_g_hash_free_from_gtype (value_gtype));
+ return ret;
+}
+
+static void
+hashtable_insert_values (GHashTable *table,
+ const GValue *key_val,
+ const GValue *value_val)
+{
+ GValue key_copy = {0, };
+ GValue value_copy = {0, };
+
+ g_value_init (&key_copy, G_VALUE_TYPE (key_val));
+ g_value_copy (key_val, &key_copy);
+ g_value_init (&value_copy, G_VALUE_TYPE (value_val));
+ g_value_copy (value_val, &value_copy);
+
+ _dbus_g_hash_table_insert_steal_values (table, &key_copy, &value_copy);
+}
+
+static void
+hashtable_foreach_copy (const GValue *key, const GValue *val, gpointer data)
+{
+ hashtable_insert_values ((GHashTable *) data, key, val);
+}
+
+static gpointer
+hashtable_copy (GType type, gpointer src)
+{
+ GHashTable *ghash;
+ GHashTable *ret;
+ GValue hashval = {0,};
+
+ ghash = src;
+
+ ret = hashtable_constructor (type);
+
+ g_value_init (&hashval, type);
+ g_value_set_static_boxed (&hashval, ghash);
+ dbus_g_type_map_value_iterate (&hashval, hashtable_foreach_copy, ret);
+ return ret;
+}
+
+/* we leave this here for backwards compatibility - any hash tables nested
+ * inside hash tables will use this as their free function if users were
+ * already relying on it, but dbus-glib itself will never use it directly as
+ * hashtable_free is also defined. */
+static void
+hashtable_simple_free (gpointer val)
+{
+ g_hash_table_unref (val);
+}
+
+struct DBusGHashTableFreeData
+{
+ GType key_gtype;
+ GType value_gtype;
+};
+
+static gboolean
+hashtable_free_foreach_steal (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ struct DBusGHashTableFreeData *data = user_data;
+ GValue val = { 0, };
+
+ g_value_init (&val, data->key_gtype);
+ gvalue_take_hash_value (&val, key);
+ g_value_unset (&val);
+
+ g_value_init (&val, data->value_gtype);
+ gvalue_take_hash_value (&val, value);
+ g_value_unset (&val);
+
+ return TRUE;
+}
+
+static void
+hashtable_free (GType type,
+ gpointer val)
+{
+ struct DBusGHashTableFreeData data = { 0, };
+ GHashTable *hash = val;
+
+ data.key_gtype = dbus_g_type_get_map_key_specialization (type);
+ data.value_gtype = dbus_g_type_get_map_value_specialization (type);
+
+ /* wheee, fun. two cases here. either:
+ *
+ * a) the keys and value types both have simple (ie, no * GType parameter is
+ * needed to know how to free them) free functions, in which case they were
+ * set as the hash free functions when the hash table was constructed. in
+ * this case, it's sufficient for us to unref the hash table as before. we
+ * have to keep doing this in order to maintain compatibility with the ABI
+ * which was around before hash tables could contain types which don't have
+ * simple free functions (such as GPtrArrays of other stuff). for these
+ * tables, users were able to ref the hash tables and add/remove values, and
+ * rely on meaningful free functions.
+ *
+ * b) for any other key or value types where /do/ need to know the GType in
+ * order to free it, this function is the only "right" way to free the hash
+ * table. both the key and value free functions were set to print a big nasty
+ * warning, and we free the contents of the hashtable with foreach_steal.
+ */
+ if (gtype_can_simple_free (data.key_gtype) &&
+ gtype_can_simple_free (data.value_gtype))
+ {
+ g_hash_table_unref (hash);
+ }
+ else
+ {
+ g_hash_table_foreach_steal (hash, hashtable_free_foreach_steal, &data);
+ g_hash_table_unref (hash);
+ }
+}
+
+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;
+ guint elt_size;
+ GType elt_type;
+ gboolean zero_terminated;
+ gboolean clear;
+
+ elt_type = dbus_g_type_get_collection_specialization (type);
+ g_assert (elt_type != G_TYPE_INVALID);
+
+ elt_size = _dbus_g_type_fixed_get_size (elt_type);
+
+ /* These are "safe" defaults */
+ zero_terminated = TRUE; /* ((struct _DBusGRealArray*) garray)->zero_terminated; */
+ clear = TRUE; /* ((struct _DBusGRealArray*) garray)->clear; */
+
+ array = g_array_new (zero_terminated, clear, elt_size);
+ return array;
+}
+
+static void
+array_iterator (GType garray_type,
+ gpointer instance,
+ DBusGTypeSpecializedCollectionIterator iterator,
+ gpointer user_data)
+{
+ GArray *array;
+ GType elt_gtype;
+ guint i;
+
+ array = instance;
+
+ elt_gtype = dbus_g_type_get_collection_specialization (garray_type);
+
+ for (i = 0; i < array->len; i++)
+ {
+ GValue val = {0, };
+ g_value_init (&val, elt_gtype);
+
+ switch (elt_gtype)
+ {
+ case G_TYPE_BOOLEAN:
+ g_value_set_boolean (&val, !!g_array_index (array, gboolean, i));
+ break;
+
+ case G_TYPE_FLOAT:
+ g_value_set_float (&val, g_array_index (array, gfloat, i));
+ break;
+
+ case G_TYPE_DOUBLE:
+ g_value_set_double (&val, g_array_index (array, gdouble, i));
+ break;
+
+ case G_TYPE_CHAR:
+ g_value_set_char (&val, g_array_index (array, gchar, i));
+ break;
+
+ case G_TYPE_UCHAR:
+ g_value_set_uchar (&val, g_array_index (array, guchar, i));
+ break;
+
+ case G_TYPE_INT:
+ g_value_set_int (&val, g_array_index (array, gint, i));
+ break;
+
+ case G_TYPE_UINT:
+ g_value_set_uint (&val, g_array_index (array, guint, i));
+ break;
+
+ case G_TYPE_LONG:
+ g_value_set_long (&val, g_array_index (array, glong, i));
+ break;
+
+ case G_TYPE_ULONG:
+ g_value_set_ulong (&val, g_array_index (array, gulong, i));
+ break;
+
+ case G_TYPE_INT64:
+ g_value_set_int64 (&val, g_array_index (array, gint64, i));
+ break;
+
+ case G_TYPE_UINT64:
+ g_value_set_uint64 (&val, g_array_index (array, guint64, i));
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ iterator (&val, user_data);
+ }
+}
+
+static void
+array_append (DBusGTypeSpecializedAppendContext *ctx,
+ GValue *value)
+{
+ GArray *array = g_value_get_boxed (ctx->val);
+ GType elt_gtype;
+ union {
+ guint64 u64;
+ gint64 i64;
+ gulong ul;
+ glong l;
+ guint u;
+ gint i;
+ guchar uc;
+ gchar c;
+ gboolean b;
+ gfloat f;
+ gdouble d;
+ } tmp;
+
+ elt_gtype = dbus_g_type_get_collection_specialization (
+ G_VALUE_TYPE (ctx->val));
+
+ switch (elt_gtype)
+ {
+ case G_TYPE_BOOLEAN:
+ tmp.b = g_value_get_boolean (value);
+ g_array_append_val (array, tmp.b);
+ break;
+
+ case G_TYPE_FLOAT:
+ tmp.f = g_value_get_float (value);
+ g_array_append_val (array, tmp.f);
+ break;
+
+ case G_TYPE_DOUBLE:
+ tmp.d = g_value_get_double (value);
+ g_array_append_val (array, tmp.d);
+ break;
+
+ case G_TYPE_CHAR:
+ tmp.c = g_value_get_char (value);
+ g_array_append_val (array, tmp.c);
+ break;
+
+ case G_TYPE_UCHAR:
+ tmp.uc = g_value_get_uchar (value);
+ g_array_append_val (array, tmp.uc);
+ break;
+
+ case G_TYPE_INT:
+ tmp.i = g_value_get_int (value);
+ g_array_append_val (array, tmp.i);
+ break;
+
+ case G_TYPE_UINT:
+ tmp.u = g_value_get_uint (value);
+ g_array_append_val (array, tmp.u);
+ break;
+
+ case G_TYPE_LONG:
+ tmp.l = g_value_get_long (value);
+ g_array_append_val (array, tmp.l);
+ break;
+
+ case G_TYPE_ULONG:
+ tmp.ul = g_value_get_ulong (value);
+ g_array_append_val (array, tmp.ul);
+ break;
+
+ case G_TYPE_INT64:
+ tmp.i64 = g_value_get_int64 (value);
+ g_array_append_val (array, tmp.i64);
+ break;
+
+ case G_TYPE_UINT64:
+ tmp.u64 = g_value_get_uint64 (value);
+ g_array_append_val (array, tmp.u64);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static gpointer
+array_copy (GType type, gpointer src)
+{
+ GArray *garray;
+ GArray *new;
+
+ garray = src;
+
+ new = array_constructor (type);
+ g_array_append_vals (new, garray->data, garray->len);
+
+ return new;
+}
+
+static void
+array_simple_free (gpointer val)
+{
+ GArray *array;
+ array = val;
+ g_array_free (array, TRUE);
+}
+
+static gboolean
+array_fixed_accessor (GType type, gpointer instance, gpointer *values, guint *len)
+{
+ GType elt_type;
+ GArray *array = instance;
+
+ elt_type = dbus_g_type_get_collection_specialization (type);
+ if (!_dbus_g_type_is_fixed (elt_type))
+ return FALSE;
+
+ *values = array->data;
+ *len = array->len;
+ return TRUE;
+}
+
+static gpointer
+ptrarray_constructor (GType type)
+{
+ /* Later we should determine a destructor, need g_ptr_array_destroy */
+ return g_ptr_array_new ();
+}
+
+static void
+gvalue_take_ptrarray_value (GValue *value, gpointer instance)
+{
+ switch (g_type_fundamental (G_VALUE_TYPE (value)))
+ {
+ case G_TYPE_STRING:
+ g_value_take_string (value, instance);
+ break;
+ case G_TYPE_BOXED:
+ g_value_take_boxed (value, instance);
+ break;
+ case G_TYPE_OBJECT:
+ g_value_take_object (value, instance);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static gpointer
+ptrarray_value_from_gvalue (const GValue *value)
+{
+ GValue tmp = {0, };
+
+ /* if the NOCOPY flag is set, then value was created via set_static and hence
+ * is not owned by us. in order to preserve the "take" semantics that the API
+ * has in general (which avoids copying in the common case), we must copy any
+ * static values so that we can indiscriminately free the entire collection
+ * later. */
+ if (value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS)
+ {
+ g_value_init (&tmp, G_VALUE_TYPE (value));
+ g_value_copy (value, &tmp);
+ value = &tmp;
+ }
+
+ switch (g_type_fundamental (G_VALUE_TYPE (value)))
+ {
+ case G_TYPE_STRING:
+ return (gpointer) g_value_get_string (value);
+ break;
+ case G_TYPE_BOXED:
+ return g_value_get_boxed (value);
+ break;
+ case G_TYPE_OBJECT:
+ return g_value_get_object (value);
+ break;
+ default:
+ g_assert_not_reached ();
+ return NULL;
+ }
+}
+
+static void
+ptrarray_iterator (GType ptrarray_type,
+ gpointer instance,
+ DBusGTypeSpecializedCollectionIterator iterator,
+ gpointer user_data)
+{
+ GPtrArray *ptrarray;
+ GType elt_gtype;
+ guint i;
+
+ ptrarray = instance;
+
+ elt_gtype = dbus_g_type_get_collection_specialization (ptrarray_type);
+
+ for (i = 0; i < ptrarray->len; i++)
+ {
+ GValue val = {0, };
+ g_value_init (&val, elt_gtype);
+ gvalue_take_ptrarray_value (&val, g_ptr_array_index (ptrarray, i));
+ iterator (&val, user_data);
+ }
+}
+
+static void
+ptrarray_copy_elt (const GValue *val, gpointer user_data)
+{
+ GPtrArray *dest = user_data;
+ GValue val_copy = {0, };
+
+ g_value_init (&val_copy, G_VALUE_TYPE (val));
+ g_value_copy (val, &val_copy);
+
+ g_ptr_array_add (dest, ptrarray_value_from_gvalue (&val_copy));
+}
+
+static gpointer
+ptrarray_copy (GType type, gpointer src)
+{
+ GPtrArray *new;
+ GValue array_val = {0, };
+
+ g_value_init (&array_val, type);
+ g_value_set_static_boxed (&array_val, src);
+
+ new = ptrarray_constructor (type);
+ dbus_g_type_collection_value_iterate (&array_val, ptrarray_copy_elt, new);
+
+ return new;
+}
+
+static void
+ptrarray_append (DBusGTypeSpecializedAppendContext *ctx, GValue *value)
+{
+ GPtrArray *array;
+
+ array = g_value_get_boxed (ctx->val);
+
+ g_ptr_array_add (array, ptrarray_value_from_gvalue (value));
+}
+
+static void
+ptrarray_free (GType type, gpointer val)
+{
+ GPtrArray *array;
+ GValue elt_val = {0, };
+ GType elt_gtype;
+ unsigned int i;
+
+ array = val;
+
+ elt_gtype = dbus_g_type_get_collection_specialization (type);
+
+ for (i = 0; i < array->len; i++)
+ {
+ g_value_init (&elt_val, elt_gtype);
+ gvalue_take_ptrarray_value (&elt_val, g_ptr_array_index (array, i));
+ g_value_unset (&elt_val);
+ }
+
+ g_ptr_array_free (array, TRUE);
+}
+
+static gpointer
+slist_constructor (GType type)
+{
+ return NULL;
+}
+
+static void
+slist_iterator (GType list_type,
+ gpointer instance,
+ DBusGTypeSpecializedCollectionIterator iterator,
+ gpointer user_data)
+{
+ GSList *slist;
+ GType elt_gtype;
+
+ slist = instance;
+
+ elt_gtype = dbus_g_type_get_collection_specialization (list_type);
+
+ for (slist = instance; slist != NULL; slist = slist->next)
+ {
+ GValue val = {0, };
+ g_value_init (&val, elt_gtype);
+ gvalue_take_ptrarray_value (&val, slist->data);
+ iterator (&val, user_data);
+ }
+}
+
+static void
+slist_copy_elt (const GValue *val, gpointer user_data)
+{
+ GSList **dest = user_data;
+ GValue val_copy = {0, };
+
+ g_value_init (&val_copy, G_VALUE_TYPE (val));
+ g_value_copy (val, &val_copy);
+
+ *dest = g_slist_append (*dest, ptrarray_value_from_gvalue (&val_copy));
+}
+
+static gpointer
+slist_copy (GType type, gpointer src)
+{
+ GSList *new;
+ GValue slist_val = {0, };
+
+ g_value_init (&slist_val, type);
+ g_value_set_static_boxed (&slist_val, src);
+
+ new = slist_constructor (type);
+ dbus_g_type_collection_value_iterate (&slist_val, slist_copy_elt, &new);
+
+ return new;
+}
+
+static void
+slist_append (DBusGTypeSpecializedAppendContext *ctx, GValue *value)
+{
+ GSList *list;
+
+ list = g_value_get_boxed (ctx->val);
+ list = g_slist_prepend (list, ptrarray_value_from_gvalue (value));
+ g_value_set_static_boxed (ctx->val, list);
+}
+
+static void
+slist_end_append (DBusGTypeSpecializedAppendContext *ctx)
+{
+ GSList *list;
+
+ /* if you append multiple times to the slist, this will reverse the existing
+ * elements... we need an init_append function */
+ list = g_value_get_boxed (ctx->val);
+ list = g_slist_reverse (list);
+
+ g_value_take_boxed (ctx->val, list);
+}
+
+static void
+slist_free (GType type, gpointer val)
+{
+ GSList *list;
+ GType elt_gtype;
+ list = val;
+
+ elt_gtype = dbus_g_type_get_collection_specialization (type);
+
+ while (list != NULL)
+ {
+ GValue elt_val = {0, };
+ g_value_init (&elt_val, elt_gtype);
+ gvalue_take_ptrarray_value (&elt_val, list->data);
+ g_value_unset (&elt_val);
+ list = g_slist_next(list);
+ }
+ list=val;
+ g_slist_free (list);
+}
+
+void
+_dbus_g_type_specialized_builtins_init (void)
+{
+ /* types with a simple_free function can be freed at run-time without
+ * the destroy function needing to know the type, so they can be
+ * stored in hash tables */
+
+ static const DBusGTypeSpecializedCollectionVtable array_vtable = {
+ {
+ array_constructor,
+ NULL,
+ array_copy,
+ array_simple_free,
+ NULL,
+ NULL,
+ },
+ array_fixed_accessor,
+ array_iterator,
+ array_append,
+ NULL
+ };
+
+
+ static const DBusGTypeSpecializedCollectionVtable ptrarray_vtable = {
+ {
+ ptrarray_constructor,
+ ptrarray_free,
+ ptrarray_copy,
+ NULL,
+ NULL,
+ NULL,
+ },
+ NULL,
+ ptrarray_iterator,
+ ptrarray_append,
+ NULL,
+ };
+
+
+ static const DBusGTypeSpecializedCollectionVtable slist_vtable = {
+ {
+ slist_constructor,
+ slist_free,
+ slist_copy,
+ NULL,
+ NULL,
+ NULL,
+ },
+ NULL,
+ slist_iterator,
+ slist_append,
+ slist_end_append,
+ };
+
+ static const DBusGTypeSpecializedMapVtable hashtable_vtable = {
+ {
+ hashtable_constructor,
+ hashtable_free,
+ hashtable_copy,
+ hashtable_simple_free,
+ NULL,
+ NULL
+ },
+ hashtable_iterator,
+ 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);
+}
Index: dbus-glib-0.112-new/dbus/dbus-gvalue.c
===================================================================
--- dbus-glib-0.112-new/dbus/dbus-gvalue.c (nonexistent)
+++ dbus-glib-0.112-new/dbus/dbus-gvalue.c (revision 5)
@@ -0,0 +1,2101 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-gvalue.c GValue to-from DBusMessageIter
+ *
+ * Copyright (C) 2004 Ximian, Inc.
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "dbus-gtest.h"
+#include "dbus-gvalue.h"
+#include "dbus-gsignature.h"
+#include "dbus-gobject.h"
+#include "dbus-gvalue-utils.h"
+#include "dbus/dbus-glib.h"
+#include <string.h>
+#include <glib.h>
+#include "dbus/dbus-signature.h"
+
+/* Seems reasonable, but this should probably be part of the standard protocol */
+#define DBUS_GLIB_MAX_VARIANT_RECURSION 32
+
+static gboolean demarshal_static_variant (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error);
+
+
+static gboolean marshal_basic (DBusMessageIter *iter,
+ const GValue *value);
+static gboolean demarshal_basic (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error);
+static gboolean marshal_strv (DBusMessageIter *iter,
+ const GValue *value);
+static gboolean demarshal_strv (DBusGValueMarshalCtx *context,
+ 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,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error);
+static gboolean marshal_proxy (DBusMessageIter *iter,
+ const GValue *value);
+static gboolean demarshal_proxy (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error);
+static gboolean marshal_object_path (DBusMessageIter *iter,
+ const GValue *value);
+static gboolean demarshal_object_path (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error);
+static gboolean marshal_object (DBusMessageIter *iter,
+ const GValue *value);
+static gboolean demarshal_object (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error);
+static gboolean marshal_signature (DBusMessageIter *iter,
+ const GValue *value);
+static gboolean demarshal_signature (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error);
+static gboolean marshal_map (DBusMessageIter *iter,
+ const GValue *value);
+static gboolean demarshal_map (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error);
+
+static gboolean marshal_collection (DBusMessageIter *iter,
+ const GValue *value);
+static gboolean marshal_collection_ptrarray (DBusMessageIter *iter,
+ const GValue *value);
+static gboolean marshal_collection_array (DBusMessageIter *iter,
+ const GValue *value);
+static gboolean demarshal_collection (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error);
+static gboolean demarshal_collection_ptrarray (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error);
+static gboolean demarshal_collection_array (DBusGValueMarshalCtx *context,
+ 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);
+typedef gboolean (*DBusGValueDemarshalFunc) (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error);
+
+typedef struct {
+ DBusGValueMarshalFunc marshaller;
+ DBusGValueDemarshalFunc demarshaller;
+} DBusGTypeMarshalVtable;
+
+typedef struct {
+ const char *sig;
+ const DBusGTypeMarshalVtable *vtable;
+} DBusGTypeMarshalData;
+
+static GQuark
+dbus_g_type_metadata_data_quark ()
+{
+ static GQuark quark;
+ if (!quark)
+ quark = g_quark_from_static_string ("DBusGTypeMetaData");
+
+ return quark;
+}
+
+static void
+set_type_metadata (GType type, const DBusGTypeMarshalData *data)
+{
+ g_type_set_qdata (type, dbus_g_type_metadata_data_quark (), (gpointer) data);
+}
+
+static void
+register_basic (int typecode, const DBusGTypeMarshalData *typedata)
+{
+ set_type_metadata (_dbus_gtype_from_basic_typecode (typecode), typedata);
+}
+
+void
+_dbus_g_value_types_init (void)
+{
+ static gboolean types_initialized;
+
+ static const DBusGTypeMarshalVtable basic_vtable = {
+ marshal_basic,
+ demarshal_basic
+ };
+
+ if (types_initialized)
+ return;
+
+ dbus_g_type_specialized_init ();
+
+ /* Register basic types */
+ {
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_BOOLEAN_AS_STRING,
+ &basic_vtable,
+ };
+ register_basic (DBUS_TYPE_BOOLEAN, &typedata);
+ }
+ {
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_BYTE_AS_STRING,
+ &basic_vtable,
+ };
+ register_basic (DBUS_TYPE_BYTE, &typedata);
+ }
+ {
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_INT16_AS_STRING,
+ &basic_vtable,
+ };
+ register_basic (DBUS_TYPE_INT16, &typedata);
+ }
+ {
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_UINT16_AS_STRING,
+ &basic_vtable,
+ };
+ register_basic (DBUS_TYPE_UINT16, &typedata);
+ }
+ {
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_UINT32_AS_STRING,
+ &basic_vtable,
+ };
+ register_basic (DBUS_TYPE_UINT32, &typedata);
+ }
+ {
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_INT32_AS_STRING,
+ &basic_vtable,
+ };
+ register_basic (DBUS_TYPE_INT32, &typedata);
+ }
+ {
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_UINT64_AS_STRING,
+ &basic_vtable,
+ };
+ register_basic (DBUS_TYPE_UINT64, &typedata);
+ }
+ {
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_INT64_AS_STRING,
+ &basic_vtable,
+ };
+ register_basic (DBUS_TYPE_INT64, &typedata);
+ }
+ {
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_DOUBLE_AS_STRING,
+ &basic_vtable,
+ };
+ register_basic (DBUS_TYPE_DOUBLE, &typedata);
+ }
+ {
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_STRING_AS_STRING,
+ &basic_vtable,
+ };
+ register_basic (DBUS_TYPE_STRING, &typedata);
+ }
+ /* fundamental GTypes that don't map 1:1 with D-BUS types */
+ {
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_BYTE_AS_STRING,
+ &basic_vtable,
+ };
+ set_type_metadata (G_TYPE_CHAR, &typedata);
+ }
+ {
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_INT32_AS_STRING,
+ &basic_vtable,
+ };
+ set_type_metadata (G_TYPE_LONG, &typedata);
+ }
+ {
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_UINT32_AS_STRING,
+ &basic_vtable,
+ };
+ set_type_metadata (G_TYPE_ULONG, &typedata);
+ }
+ {
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_DOUBLE_AS_STRING,
+ &basic_vtable,
+ };
+ set_type_metadata (G_TYPE_FLOAT, &typedata);
+ }
+
+ /* Register complex types with builtin GType mappings */
+ {
+ static const DBusGTypeMarshalVtable vtable = {
+ marshal_variant,
+ demarshal_variant
+ };
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_VARIANT_AS_STRING,
+ &vtable
+ };
+ set_type_metadata (G_TYPE_VALUE, &typedata);
+ };
+ {
+ static const DBusGTypeMarshalVtable vtable = {
+ marshal_strv,
+ demarshal_strv
+ };
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
+ &vtable
+ };
+ set_type_metadata (G_TYPE_STRV, &typedata);
+ };
+
+
+ /* Register some types specific to the D-BUS GLib bindings */
+ {
+ static const DBusGTypeMarshalVtable vtable = {
+ marshal_proxy,
+ demarshal_proxy
+ };
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_OBJECT_PATH_AS_STRING,
+ &vtable
+ };
+ set_type_metadata (DBUS_TYPE_G_PROXY, &typedata);
+ }
+
+ {
+ static const DBusGTypeMarshalVtable vtable = {
+ marshal_object_path,
+ demarshal_object_path
+ };
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_OBJECT_PATH_AS_STRING,
+ &vtable
+ };
+ set_type_metadata (DBUS_TYPE_G_OBJECT_PATH, &typedata);
+ }
+
+ {
+ static const DBusGTypeMarshalVtable vtable = {
+ marshal_object,
+ demarshal_object
+ };
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_OBJECT_PATH_AS_STRING,
+ &vtable
+ };
+ set_type_metadata (G_TYPE_OBJECT, &typedata);
+ }
+
+ {
+ static const DBusGTypeMarshalVtable vtable = {
+ marshal_signature,
+ demarshal_signature
+ };
+ static const DBusGTypeMarshalData typedata = {
+ DBUS_TYPE_SIGNATURE_AS_STRING,
+ &vtable
+ };
+ set_type_metadata (DBUS_TYPE_G_SIGNATURE, &typedata);
+ }
+
+ types_initialized = TRUE;
+}
+
+/**
+ * DBusGObjectPath:
+ *
+ * A typedef for a string used to represent D-Bus object paths.
+ * Its GType is %DBUS_TYPE_G_OBJECT_PATH, derived from %G_TYPE_BOXED.
+ *
+ * Prior to version 0.FIXME this was used as the type name of
+ * %DBUS_TYPE_G_OBJECT_PATH, but did not actually exist as a typedef.
+ *
+ * Since: 0.FIXME
+ *
+ * Deprecated: New code should use GDBus instead. The closest equivalent
+ * is a #GVariant (%G_TYPE_VARIANT) of type %G_VARIANT_TYPE_OBJECT_PATH.
+ */
+
+/**
+ * DBUS_TYPE_G_OBJECT_PATH:
+ *
+ * The #GType of a #DBusGObjectPath, which is a boxed type containing a
+ * D-Bus object path as a zero-terminated string. Object paths can be
+ * copied with g_strdup() and freed with g_free(), just like %G_TYPE_STRING,
+ * but have a distinct boxed type to allow them to be distinguished when
+ * stored in a #GValue.
+ *
+ * Returns: a type derived from %G_TYPE_BOXED
+ *
+ * Deprecated: New code should use GDBus instead. The closest equivalent
+ * is a #GVariant (%G_TYPE_VARIANT) of type %G_VARIANT_TYPE_OBJECT_PATH.
+ */
+GType
+dbus_g_object_path_get_g_type (void)
+{
+ static GType type_id = 0;
+
+ if (!type_id)
+ type_id = g_boxed_type_register_static ("DBusGObjectPath",
+ (GBoxedCopyFunc) g_strdup,
+ (GBoxedFreeFunc) g_free);
+ return type_id;
+}
+
+/**
+ * DBusGSignature:
+ *
+ * A typedef for a string used to represent D-Bus signatures.
+ * Its GType is %DBUS_TYPE_G_SIGNATURE, derived from %G_TYPE_BOXED.
+ *
+ * Prior to version 0.FIXME this was used as the type name of
+ * %DBUS_TYPE_G_SIGNATURE, but did not actually exist as a typedef.
+ *
+ * Since: 0.FIXME
+ *
+ * Deprecated: New code should use GDBus instead. The closest equivalent
+ * is a #GVariant (%G_TYPE_VARIANT) of type %G_VARIANT_TYPE_SIGNATURE.
+ */
+
+/**
+ * DBUS_TYPE_G_SIGNATURE:
+ *
+ * The #GType of a #DBusGSignature, which is a boxed type containing a
+ * D-Bus signature as a zero-terminated string. Signatures can be
+ * copied with g_strdup() and freed with g_free(), just like %G_TYPE_STRING,
+ * but have a distinct boxed type to allow them to be distinguished when
+ * stored in a #GValue.
+ *
+ * Returns: a type derived from %G_TYPE_BOXED
+ *
+ * Deprecated: New code should use GDBus instead. The closest equivalent
+ * is a #GVariant (%G_TYPE_VARIANT) of type %G_VARIANT_TYPE_SIGNATURE.
+ */
+GType
+dbus_g_signature_get_g_type (void)
+{
+ static GType type_id = 0;
+
+ if (G_UNLIKELY (type_id == 0))
+ type_id = g_boxed_type_register_static ("DBusGSignature",
+ (GBoxedCopyFunc) g_strdup,
+ (GBoxedFreeFunc) g_free);
+
+ return type_id;
+}
+
+
+char *
+_dbus_gtype_to_signature (GType gtype)
+{
+ char *ret;
+ DBusGTypeMarshalData *typedata;
+
+ if (dbus_g_type_is_collection (gtype))
+ {
+ GType elt_gtype;
+ char *subsig;
+
+ elt_gtype = dbus_g_type_get_collection_specialization (gtype);
+ subsig = _dbus_gtype_to_signature (elt_gtype);
+ ret = g_strconcat (DBUS_TYPE_ARRAY_AS_STRING, subsig, NULL);
+ g_free (subsig);
+ }
+ else if (dbus_g_type_is_map (gtype))
+ {
+ GType key_gtype;
+ GType val_gtype;
+ char *key_subsig;
+ char *val_subsig;
+
+ key_gtype = dbus_g_type_get_map_key_specialization (gtype);
+ val_gtype = dbus_g_type_get_map_value_specialization (gtype);
+ key_subsig = _dbus_gtype_to_signature (key_gtype);
+ val_subsig = _dbus_gtype_to_signature (val_gtype);
+ ret = g_strconcat (DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING, key_subsig, val_subsig, DBUS_DICT_ENTRY_END_CHAR_AS_STRING, NULL);
+ 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++)
+ {
+ gchar *subsig;
+ subsig = _dbus_gtype_to_signature (
+ dbus_g_type_get_struct_member_type (gtype, i));
+ g_string_append (sig, subsig);
+ g_free (subsig);
+ }
+ 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 ());
+ if (typedata == NULL)
+ return NULL;
+ ret = g_strdup (typedata->sig);
+ }
+ return ret;
+}
+
+char *
+_dbus_gvalue_to_signature (const GValue *val)
+{
+ GType gtype;
+
+ gtype = G_VALUE_TYPE (val);
+ if (g_type_is_a (gtype, G_TYPE_ARRAY))
+ {
+ GString *str;
+ guint i;
+ GValueArray *array;
+
+ array = g_value_get_boxed (val);
+
+ str = g_string_new (DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
+ 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);
+ }
+ g_string_append (str, DBUS_STRUCT_END_CHAR_AS_STRING);
+
+ return g_string_free (str, FALSE);
+ }
+ else
+ return _dbus_gtype_to_signature (gtype);
+}
+
+static gboolean
+demarshal_basic (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error)
+{
+ int current_type;
+
+ current_type = dbus_message_iter_get_arg_type (iter);
+ g_assert (dbus_type_is_basic (current_type));
+
+ switch (current_type)
+ {
+ case DBUS_TYPE_BOOLEAN:
+ {
+ dbus_bool_t bool;
+ if (!G_VALUE_HOLDS (value, G_TYPE_BOOLEAN))
+ goto invalid_type;
+ dbus_message_iter_get_basic (iter, &bool);
+ g_value_set_boolean (value, bool);
+ return TRUE;
+ }
+ case DBUS_TYPE_BYTE:
+ {
+ unsigned char byte;
+ if (!G_VALUE_HOLDS (value, G_TYPE_UCHAR))
+ goto invalid_type;
+ dbus_message_iter_get_basic (iter, &byte);
+ g_value_set_uchar (value, byte);
+ return TRUE;
+ }
+ case DBUS_TYPE_INT32:
+ {
+ dbus_int32_t intval;
+ if (!G_VALUE_HOLDS (value, G_TYPE_INT))
+ goto invalid_type;
+ dbus_message_iter_get_basic (iter, &intval);
+ g_value_set_int (value, intval);
+ return TRUE;
+ }
+ case DBUS_TYPE_UINT32:
+ {
+ dbus_uint32_t intval;
+ if (!G_VALUE_HOLDS (value, G_TYPE_UINT))
+ goto invalid_type;
+ dbus_message_iter_get_basic (iter, &intval);
+ g_value_set_uint (value, intval);
+ return TRUE;
+ }
+ case DBUS_TYPE_INT64:
+ {
+ dbus_int64_t intval;
+ if (!G_VALUE_HOLDS (value, G_TYPE_INT64))
+ goto invalid_type;
+ dbus_message_iter_get_basic (iter, &intval);
+ g_value_set_int64 (value, intval);
+ return TRUE;
+ }
+ case DBUS_TYPE_UINT64:
+ {
+ dbus_uint64_t intval;
+ if (!G_VALUE_HOLDS (value, G_TYPE_UINT64))
+ goto invalid_type;
+ dbus_message_iter_get_basic (iter, &intval);
+ g_value_set_uint64 (value, intval);
+ return TRUE;
+ }
+ case DBUS_TYPE_DOUBLE:
+ {
+ double dval;
+ if (!G_VALUE_HOLDS (value, G_TYPE_DOUBLE))
+ goto invalid_type;
+ dbus_message_iter_get_basic (iter, &dval);
+ g_value_set_double (value, dval);
+ return TRUE;
+ }
+ case DBUS_TYPE_INT16:
+ {
+ dbus_int16_t v;
+ if (!G_VALUE_HOLDS (value, G_TYPE_INT))
+ goto invalid_type;
+ dbus_message_iter_get_basic (iter, &v);
+ g_value_set_int (value, v);
+ return TRUE;
+ }
+ case DBUS_TYPE_UINT16:
+ {
+ dbus_uint16_t v;
+ if (!G_VALUE_HOLDS (value, G_TYPE_UINT))
+ goto invalid_type;
+ dbus_message_iter_get_basic (iter, &v);
+ g_value_set_uint (value, v);
+ return TRUE;
+ }
+ case DBUS_TYPE_STRING:
+ {
+ const char *s;
+ if (!G_VALUE_HOLDS (value, G_TYPE_STRING))
+ goto invalid_type;
+ dbus_message_iter_get_basic (iter, &s);
+ g_value_set_string (value, s);
+ return TRUE;
+ }
+ default:
+ /* fall through to invalid_type */
+ break;
+ }
+ invalid_type:
+ g_set_error (error,
+ DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ "Expected type %s, got type code \'%c\'",
+ g_type_name (G_VALUE_TYPE (value)),
+ (guchar) current_type);
+ return FALSE;
+}
+
+static gboolean
+demarshal_static_variant (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error)
+{
+ char *sig;
+ DBusMessageIter subiter;
+ GType variant_type;
+
+ dbus_message_iter_recurse (iter, &subiter);
+ sig = dbus_message_iter_get_signature (&subiter);
+
+ variant_type = _dbus_gtype_from_signature (sig, context->proxy != NULL);
+ if (variant_type == G_TYPE_INVALID)
+ {
+ /* It can happen if we received an unknown type such as
+ * DBUS_TYPE_UNIX_FD or DBUS_TYPE_MAYBE. */
+ g_set_error (error, DBUS_GERROR,
+ DBUS_GERROR_INVALID_SIGNATURE,
+ "Variant contains unknown signature \'%s\'", sig);
+ dbus_free (sig);
+ return FALSE;
+ }
+
+ dbus_free (sig);
+
+ g_value_init (value, variant_type);
+
+ if (!_dbus_gvalue_demarshal (context, &subiter, value, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+demarshal_variant (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error)
+
+{
+ GValue *variant_val;
+ variant_val = g_new0 (GValue, 1);
+
+ if (!demarshal_static_variant (context, iter, variant_val, error))
+ return FALSE;
+
+ g_value_take_boxed (value, variant_val);
+ return TRUE;
+}
+
+static gboolean
+demarshal_proxy (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error)
+{
+ DBusGProxy *new_proxy;
+ const char *objpath;
+ int current_type;
+
+ current_type = dbus_message_iter_get_arg_type (iter);
+ if (current_type != DBUS_TYPE_OBJECT_PATH)
+ {
+ g_set_error (error,
+ DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ "Expected D-BUS object path, got type code \'%c\'", (guchar) current_type);
+ return FALSE;
+ }
+
+ g_assert (context->proxy != NULL);
+
+ dbus_message_iter_get_basic (iter, &objpath);
+
+ new_proxy = dbus_g_proxy_new_from_proxy (context->proxy, NULL, objpath);
+ g_value_take_object (value, new_proxy);
+
+ return TRUE;
+}
+
+static gboolean
+demarshal_object_path (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error)
+{
+ const char *objpath;
+ int current_type;
+
+ current_type = dbus_message_iter_get_arg_type (iter);
+ if (current_type != DBUS_TYPE_OBJECT_PATH)
+ {
+ g_set_error (error,
+ DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ "Expected D-BUS object path, got type code \'%c\'", (guchar) current_type);
+ return FALSE;
+ }
+
+ dbus_message_iter_get_basic (iter, &objpath);
+
+ g_value_set_boxed (value, objpath);
+
+ return TRUE;
+}
+
+static gboolean
+demarshal_object (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error)
+{
+ const char *objpath;
+ int current_type;
+ GObject *obj;
+
+ current_type = dbus_message_iter_get_arg_type (iter);
+ if (current_type != DBUS_TYPE_OBJECT_PATH)
+ {
+ g_set_error (error,
+ DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ "Expected D-BUS object path, got type code \'%c\'", (guchar) current_type);
+ return FALSE;
+ }
+ g_assert (context->proxy == NULL);
+
+ dbus_message_iter_get_basic (iter, &objpath);
+
+ obj = dbus_g_connection_lookup_g_object (context->gconnection, objpath);
+ if (obj == NULL)
+ {
+ g_set_error (error,
+ DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ "Unregistered object at path '%s'",
+ objpath);
+ return FALSE;
+ }
+ g_value_set_object (value, obj);
+
+ return TRUE;
+}
+
+static gboolean
+demarshal_signature (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error)
+{
+ const char *sig;
+ int current_type;
+
+ current_type = dbus_message_iter_get_arg_type (iter);
+ if (current_type != DBUS_TYPE_SIGNATURE)
+ {
+ g_set_error (error,
+ DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ "Expected D-BUS signature, got type code \'%c\'", (guchar) current_type);
+ return FALSE;
+ }
+
+ dbus_message_iter_get_basic (iter, &sig);
+
+ g_value_set_boxed (value, sig);
+
+ return TRUE;
+}
+
+static gboolean
+demarshal_strv (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error)
+{
+ DBusMessageIter subiter;
+ int current_type;
+ GArray *arr;
+
+ current_type = dbus_message_iter_get_arg_type (iter);
+ if (current_type != DBUS_TYPE_ARRAY)
+ {
+ g_set_error (error,
+ DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ "Expected D-BUS array, got type code \'%c\'", (guchar) current_type);
+ return FALSE;
+ }
+
+ dbus_message_iter_recurse (iter, &subiter);
+
+ current_type = dbus_message_iter_get_arg_type (&subiter);
+ if (current_type != DBUS_TYPE_INVALID
+ && current_type != DBUS_TYPE_STRING)
+ {
+ g_set_error (error,
+ DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ "Expected D-BUS string, got type code \'%c\'", (guchar) current_type);
+ return FALSE;
+ }
+
+ arr = g_array_new (TRUE, FALSE, sizeof (char *));
+
+ while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
+ {
+ g_assert (current_type == DBUS_TYPE_STRING);
+ const char *str;
+ char *copy;
+
+ dbus_message_iter_get_basic (&subiter, &str);
+ copy = g_strdup (str);
+ g_array_append_val (arr, copy);
+
+ dbus_message_iter_next (&subiter);
+ }
+
+ g_value_take_boxed (value, arr->data);
+ g_array_free (arr, FALSE);
+
+ return TRUE;
+}
+
+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);
+
+ 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);
+ dbus_free (current_sig);
+ return FALSE;
+ }
+ dbus_free (current_sig);
+
+ 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_take_boxed (value, ret);
+
+ return TRUE;
+}
+
+static gboolean
+demarshal_map (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error)
+{
+ GType gtype;
+ DBusMessageIter subiter;
+ int current_type;
+ gpointer ret;
+ GType key_gtype;
+ GType value_gtype;
+ DBusGTypeSpecializedAppendContext appendctx;
+
+ current_type = dbus_message_iter_get_arg_type (iter);
+ if (current_type != DBUS_TYPE_ARRAY)
+ {
+ g_set_error (error,
+ DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ "Expected D-BUS array, got type code \'%c\'", (guchar) current_type);
+ return FALSE;
+ }
+
+ gtype = G_VALUE_TYPE (value);
+
+ dbus_message_iter_recurse (iter, &subiter);
+
+ current_type = dbus_message_iter_get_arg_type (&subiter);
+ if (current_type != DBUS_TYPE_INVALID
+ && current_type != DBUS_TYPE_DICT_ENTRY)
+ {
+ g_set_error (error,
+ DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ "Expected D-BUS dict entry, got type code \'%c\'", (guchar) current_type);
+ return FALSE;
+ }
+
+ key_gtype = dbus_g_type_get_map_key_specialization (gtype);
+ value_gtype = dbus_g_type_get_map_value_specialization (gtype);
+
+ ret = dbus_g_type_specialized_construct (gtype);
+ g_value_take_boxed (value, ret);
+
+ dbus_g_type_specialized_init_append (value, &appendctx);
+
+ while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
+ {
+ DBusMessageIter entry_iter;
+ GValue key_value = {0,};
+ GValue value_value = {0,};
+
+ current_type = dbus_message_iter_get_arg_type (&subiter);
+ g_assert (current_type == DBUS_TYPE_DICT_ENTRY);
+
+ dbus_message_iter_recurse (&subiter, &entry_iter);
+
+ g_value_init (&key_value, key_gtype);
+ if (!_dbus_gvalue_demarshal (context,
+ &entry_iter,
+ &key_value,
+ error))
+ return FALSE;
+
+ dbus_message_iter_next (&entry_iter);
+
+ g_value_init (&value_value, value_gtype);
+ if (!_dbus_gvalue_demarshal (context,
+ &entry_iter,
+ &value_value,
+ error))
+ return FALSE;
+
+ dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value);
+ /* Ownership of values passes to map, don't unset */
+
+ dbus_message_iter_next (&subiter);
+ }
+
+ 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_take_boxed (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)
+{
+ DBusGTypeMarshalData *typedata;
+
+ typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
+ if (typedata == NULL)
+ {
+ if (g_type_is_a (type, G_TYPE_ARRAY))
+ return demarshal_valuearray;
+ if (dbus_g_type_is_collection (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;
+ }
+ g_assert (typedata->vtable);
+ return typedata->vtable->demarshaller;
+}
+
+static gboolean
+demarshal_collection (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error)
+{
+ GType coltype;
+ GType subtype;
+
+ coltype = G_VALUE_TYPE (value);
+ subtype = dbus_g_type_get_collection_specialization (coltype);
+
+ if (_dbus_g_type_is_fixed (subtype))
+ return demarshal_collection_array (context, iter, value, error);
+ else
+ return demarshal_collection_ptrarray (context, iter, value, error);
+}
+
+static gboolean
+demarshal_collection_ptrarray (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error)
+{
+ GType coltype;
+ GType subtype;
+ gpointer instance;
+ DBusGTypeSpecializedAppendContext ctx;
+ DBusGValueDemarshalFunc demarshaller;
+ DBusMessageIter subiter;
+ int current_type;
+
+ current_type = dbus_message_iter_get_arg_type (iter);
+
+ if (current_type != DBUS_TYPE_ARRAY)
+ {
+ g_set_error (error,
+ DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ "Expected D-BUS array, got type code \'%c\'", (guchar) current_type);
+ return FALSE;
+ }
+
+ dbus_message_iter_recurse (iter, &subiter);
+
+ coltype = G_VALUE_TYPE (value);
+ subtype = dbus_g_type_get_collection_specialization (coltype);
+
+ demarshaller = get_type_demarshaller (subtype);
+
+ if (!demarshaller)
+ {
+ g_set_error (error,
+ DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ "No demarshaller registered for type \"%s\" of collection \"%s\"",
+ g_type_name (coltype),
+ g_type_name (subtype));
+ return FALSE;
+ }
+
+ instance = dbus_g_type_specialized_construct (coltype);
+ g_value_take_boxed (value, instance);
+
+ dbus_g_type_specialized_init_append (value, &ctx);
+
+ while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
+ {
+ GValue eltval = {0, };
+
+ g_value_init (&eltval, subtype);
+
+ if (!demarshaller (context, &subiter, &eltval, error))
+ {
+ dbus_g_type_specialized_collection_end_append (&ctx);
+ g_value_unset (value);
+ return FALSE;
+ }
+ dbus_g_type_specialized_collection_append (&ctx, &eltval);
+
+ dbus_message_iter_next (&subiter);
+ }
+ dbus_g_type_specialized_collection_end_append (&ctx);
+
+ return TRUE;
+}
+
+static gboolean
+demarshal_collection_array (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error)
+{
+ DBusMessageIter subiter;
+ GArray *ret;
+ GType elt_gtype;
+ int elt_size;
+ void *msgarray;
+ int msgarray_len;
+
+ dbus_message_iter_recurse (iter, &subiter);
+
+ elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
+ g_assert (elt_gtype != G_TYPE_INVALID);
+ g_assert (_dbus_g_type_is_fixed (elt_gtype));
+
+ elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
+
+ ret = g_array_new (FALSE, TRUE, elt_size);
+
+ msgarray = NULL;
+ dbus_message_iter_get_fixed_array (&subiter,
+ &msgarray,
+ &msgarray_len);
+ g_assert (msgarray != NULL || msgarray_len == 0);
+
+ if (msgarray_len)
+ g_array_append_vals (ret, msgarray, (guint) msgarray_len);
+
+ g_value_take_boxed (value, ret);
+
+ return TRUE;
+}
+
+gboolean
+_dbus_gvalue_demarshal (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error)
+{
+ GType gtype;
+ DBusGValueDemarshalFunc demarshaller;
+ gboolean retcode = FALSE;
+
+ if (context->recursion_depth > DBUS_GLIB_MAX_VARIANT_RECURSION)
+ {
+ g_set_error (error, DBUS_GERROR,
+ DBUS_GERROR_NO_MEMORY,
+ "Variant recursion limit exceeded");
+ return FALSE;
+ }
+ context->recursion_depth++;
+
+ gtype = G_VALUE_TYPE (value);
+
+ demarshaller = get_type_demarshaller (gtype);
+
+ if (demarshaller == NULL)
+ {
+ g_set_error (error,
+ DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ "No demarshaller registered for type \"%s\"",
+ g_type_name (gtype));
+
+ goto out;
+ }
+
+ retcode = demarshaller (context, iter, value, error);
+ out:
+ context->recursion_depth--;
+ return retcode;
+}
+
+gboolean
+_dbus_gvalue_demarshal_variant (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error)
+{
+ return demarshal_static_variant (context, iter, value, error);
+}
+
+GValueArray *
+_dbus_gvalue_demarshal_message (DBusGValueMarshalCtx *context,
+ DBusMessage *message,
+ guint n_types,
+ const GType *types,
+ GError **error)
+{
+ GValueArray *ret;
+ DBusMessageIter iter;
+ int current_type;
+ guint index_;
+
+ ret = g_value_array_new (6); /* 6 is a typical maximum for arguments */
+
+ dbus_message_iter_init (message, &iter);
+ index_ = 0;
+ while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
+ {
+ GValue *value;
+ GType gtype;
+
+ if (index_ >= n_types)
+ {
+ g_set_error (error, DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ "Too many arguments in message");
+ goto lose;
+ }
+
+ g_value_array_append (ret, NULL);
+ value = g_value_array_get_nth (ret, index_);
+
+ gtype = types[index_];
+ g_value_init (value, gtype);
+
+ if (!_dbus_gvalue_demarshal (context, &iter, value, error))
+ goto lose;
+ dbus_message_iter_next (&iter);
+ index_++;
+ }
+ if (index_ < n_types)
+ {
+ g_set_error (error, DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ "Too few arguments in message");
+ goto lose;
+ }
+
+ return ret;
+ lose:
+ g_value_array_free (ret);
+ return NULL;
+}
+
+static void oom (void) G_GNUC_NORETURN;
+static void
+oom (void)
+{
+ g_error ("no memory");
+}
+
+static gboolean
+marshal_basic (DBusMessageIter *iter, const GValue *value)
+{
+ GType value_type;
+
+ value_type = G_VALUE_TYPE (value);
+
+ switch (value_type)
+ {
+ case G_TYPE_CHAR:
+ {
+ char b = g_value_get_char (value);
+ if (!dbus_message_iter_append_basic (iter,
+ DBUS_TYPE_BYTE,
+ &b))
+ oom ();
+ }
+ return TRUE;
+ case G_TYPE_UCHAR:
+ {
+ unsigned char b = g_value_get_uchar (value);
+ if (!dbus_message_iter_append_basic (iter,
+ DBUS_TYPE_BYTE,
+ &b))
+ oom ();
+ }
+ return TRUE;
+ case G_TYPE_BOOLEAN:
+ {
+ dbus_bool_t b = g_value_get_boolean (value);
+
+ g_return_val_if_fail (b == TRUE || b == FALSE, FALSE);
+
+ if (!dbus_message_iter_append_basic (iter,
+ DBUS_TYPE_BOOLEAN,
+ &b))
+ oom ();
+ }
+ return TRUE;
+ case G_TYPE_INT:
+ {
+ dbus_int32_t v = g_value_get_int (value);
+ if (!dbus_message_iter_append_basic (iter,
+ DBUS_TYPE_INT32,
+ &v))
+ oom ();
+ }
+ return TRUE;
+ case G_TYPE_UINT:
+ {
+ dbus_uint32_t v = g_value_get_uint (value);
+ if (!dbus_message_iter_append_basic (iter,
+ DBUS_TYPE_UINT32,
+ &v))
+ oom ();
+ }
+ return TRUE;
+ case G_TYPE_LONG:
+ {
+ dbus_int32_t v = g_value_get_long (value);
+ if (!dbus_message_iter_append_basic (iter,
+ DBUS_TYPE_INT32,
+ &v))
+ oom ();
+ }
+ return TRUE;
+ case G_TYPE_ULONG:
+ {
+ dbus_uint32_t v = g_value_get_ulong (value);
+ if (!dbus_message_iter_append_basic (iter,
+ DBUS_TYPE_UINT32,
+ &v))
+ oom ();
+ }
+ return TRUE;
+ case G_TYPE_INT64:
+ {
+ gint64 v = g_value_get_int64 (value);
+ if (!dbus_message_iter_append_basic (iter,
+ DBUS_TYPE_INT64,
+ &v))
+ oom ();
+ }
+ return TRUE;
+ case G_TYPE_UINT64:
+ {
+ guint64 v = g_value_get_uint64 (value);
+ if (!dbus_message_iter_append_basic (iter,
+ DBUS_TYPE_UINT64,
+ &v))
+ oom ();
+ }
+ return TRUE;
+ case G_TYPE_FLOAT:
+ {
+ double v = g_value_get_float (value);
+
+ if (!dbus_message_iter_append_basic (iter,
+ DBUS_TYPE_DOUBLE,
+ &v))
+ oom ();
+ }
+ return TRUE;
+ case G_TYPE_DOUBLE:
+ {
+ double v = g_value_get_double (value);
+
+ if (!dbus_message_iter_append_basic (iter,
+ DBUS_TYPE_DOUBLE,
+ &v))
+ oom ();
+ }
+ return TRUE;
+ case G_TYPE_STRING:
+ {
+ const char *v = g_value_get_string (value);
+ if (!v)
+ v = "";
+
+ /* FIXME: fd.o #16320: consider using g_return_if_fail to check UTF-8
+ * validity */
+
+ if (!dbus_message_iter_append_basic (iter,
+ DBUS_TYPE_STRING,
+ &v))
+ {
+ gchar *s = g_strdup_value_contents (value);
+
+ g_critical ("Unable to marshal string (not UTF-8 or OOM?): %s",
+ s);
+ g_free (s);
+ return FALSE;
+ }
+ }
+ return TRUE;
+
+ default:
+ {
+ g_assert_not_reached ();
+ return FALSE;
+ }
+ }
+}
+
+static gboolean
+marshal_strv (DBusMessageIter *iter,
+ const GValue *value)
+{
+ DBusMessageIter subiter;
+ char **array;
+ char **elt;
+ gboolean ret = FALSE;
+
+ g_assert (G_VALUE_TYPE (value) == g_strv_get_type ());
+
+ array = g_value_get_boxed (value);
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_ARRAY,
+ "s",
+ &subiter))
+ goto out;
+
+ if (array)
+ {
+ for (elt = array; *elt; elt++)
+ {
+ if (!dbus_message_iter_append_basic (&subiter,
+ DBUS_TYPE_STRING,
+ elt))
+ goto out;
+ }
+ }
+
+ if (!dbus_message_iter_close_container (iter, &subiter))
+ goto out;
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+static gboolean
+marshal_valuearray (DBusMessageIter *iter,
+ const GValue *value)
+{
+ GValueArray *array;
+ guint i;
+ DBusMessageIter subiter;
+
+ g_assert (G_VALUE_TYPE (value) == G_TYPE_ARRAY);
+
+ array = g_value_get_boxed (value);
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &subiter))
+ oom ();
+
+ if (array)
+ {
+ for (i = 0; i < array->n_values; i++)
+ {
+ if (!_dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
+ {
+ dbus_message_iter_abandon_container (iter, &subiter);
+ return FALSE;
+ }
+ }
+ }
+
+ return dbus_message_iter_close_container (iter, &subiter);
+}
+
+static gboolean
+marshal_proxy (DBusMessageIter *iter,
+ const GValue *value)
+{
+ const char *path;
+ DBusGProxy *proxy;
+
+ g_assert (G_VALUE_TYPE (value) == dbus_g_proxy_get_type ());
+
+ proxy = g_value_get_object (value);
+ g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
+ path = dbus_g_proxy_get_path (proxy);
+ g_return_val_if_fail (g_variant_is_object_path (path), FALSE);
+
+ if (!dbus_message_iter_append_basic (iter,
+ DBUS_TYPE_OBJECT_PATH,
+ &path))
+ oom ();
+
+ return TRUE;
+}
+
+static gboolean
+marshal_object_path (DBusMessageIter *iter,
+ const GValue *value)
+{
+ const char *path;
+
+ g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_PATH);
+
+ path = g_value_get_boxed (value);
+ g_return_val_if_fail (g_variant_is_object_path (path), FALSE);
+
+ if (!dbus_message_iter_append_basic (iter,
+ DBUS_TYPE_OBJECT_PATH,
+ &path))
+ oom ();
+
+ return TRUE;
+}
+
+static gboolean
+marshal_object (DBusMessageIter *iter,
+ const GValue *value)
+{
+ const char *path;
+ GObject *obj;
+
+ obj = g_value_get_object (value);
+ g_return_val_if_fail (G_IS_OBJECT (obj), FALSE);
+
+ path = _dbus_gobject_get_path (obj);
+ g_return_val_if_fail (g_variant_is_object_path (path), FALSE);
+
+ if (!dbus_message_iter_append_basic (iter,
+ DBUS_TYPE_OBJECT_PATH,
+ &path))
+ oom ();
+
+ return TRUE;
+}
+
+static gboolean
+marshal_signature (DBusMessageIter *iter,
+ const GValue *value)
+{
+ const char *sig;
+
+ g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_SIGNATURE);
+
+ sig = g_value_get_boxed (value);
+ g_return_val_if_fail (g_variant_is_signature (sig), FALSE);
+
+ /* failure here isn't strictly *guaranteed* to be OOM, since GDBus might
+ * understand more type-codes than our libdbus */
+ if (!dbus_message_iter_append_basic (iter,
+ DBUS_TYPE_SIGNATURE,
+ &sig))
+ return FALSE;
+
+ return TRUE;
+}
+
+struct DBusGLibHashMarshalData
+{
+ const char *entry_sig;
+ DBusMessageIter *iter;
+ gboolean err;
+};
+
+static void
+marshal_map_entry (const GValue *key,
+ const GValue *value,
+ gpointer data)
+{
+ struct DBusGLibHashMarshalData *hashdata = data;
+ DBusMessageIter subiter;
+
+ if (hashdata->err)
+ return;
+
+ if (!dbus_message_iter_open_container (hashdata->iter,
+ DBUS_TYPE_DICT_ENTRY,
+ NULL,
+ &subiter))
+ goto lose;
+
+ if (!_dbus_gvalue_marshal (&subiter, key))
+ goto lose;
+
+ if (!_dbus_gvalue_marshal (&subiter, value))
+ goto lose;
+
+ if (!dbus_message_iter_close_container (hashdata->iter, &subiter))
+ goto lose;
+
+ return;
+ lose:
+ hashdata->err = TRUE;
+}
+
+static gboolean
+marshal_map (DBusMessageIter *iter,
+ const GValue *value)
+{
+ GType gtype;
+ DBusMessageIter arr_iter;
+ struct DBusGLibHashMarshalData hashdata;
+ char *key_sig;
+ char *value_sig;
+ GType key_type;
+ GType value_type;
+ char *entry_sig;
+ char *array_sig;
+
+ gtype = G_VALUE_TYPE (value);
+
+ key_type = dbus_g_type_get_map_key_specialization (gtype);
+ g_assert (_dbus_gtype_is_valid_hash_key (key_type));
+ value_type = dbus_g_type_get_map_value_specialization (gtype);
+ 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,
+ DBUS_DICT_ENTRY_END_CHAR);
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_ARRAY,
+ array_sig,
+ &arr_iter))
+ goto lose;
+
+ hashdata.iter = &arr_iter;
+ hashdata.err = FALSE;
+ hashdata.entry_sig = entry_sig;
+
+ dbus_g_type_map_value_iterate (value,
+ marshal_map_entry,
+ &hashdata);
+
+ if (hashdata.err)
+ {
+ dbus_message_iter_abandon_container (iter, &arr_iter);
+ goto lose;
+ }
+ else if (!dbus_message_iter_close_container (iter, &arr_iter))
+ {
+ goto lose;
+ }
+
+ out:
+ g_free (entry_sig);
+ g_free (array_sig);
+ return !hashdata.err;
+ lose:
+ hashdata.err = TRUE;
+ goto out;
+}
+
+static gboolean
+marshal_struct (DBusMessageIter *iter,
+ const GValue *value)
+{
+ GType gtype;
+ DBusMessageIter subiter;
+ guint size, i;
+ GValue val = {0,};
+
+ gtype = G_VALUE_TYPE (value);
+
+ size = dbus_g_type_get_struct_size (gtype);
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &subiter))
+ 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))
+ goto abandon;
+
+ if (!_dbus_gvalue_marshal (&subiter, &val))
+ goto abandon;
+
+ g_value_unset(&val);
+ }
+
+ return dbus_message_iter_close_container (iter, &subiter);
+
+abandon:
+ dbus_message_iter_abandon_container (iter, &subiter);
+ return FALSE;
+}
+
+static gboolean
+marshal_variant (DBusMessageIter *iter,
+ const GValue *value)
+{
+ GType value_gtype;
+ DBusMessageIter subiter;
+ char *variant_sig;
+ GValue *real_value;
+ gboolean ret = FALSE;
+
+ real_value = g_value_get_boxed (value);
+ value_gtype = G_VALUE_TYPE (real_value);
+
+ variant_sig = _dbus_gvalue_to_signature (real_value);
+ if (variant_sig == NULL)
+ {
+ g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
+ return FALSE;
+ }
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_VARIANT,
+ variant_sig,
+ &subiter))
+ goto out;
+
+ if (!_dbus_gvalue_marshal (&subiter, real_value))
+ {
+ dbus_message_iter_abandon_container (iter, &subiter);
+ goto out;
+ }
+
+ if (!dbus_message_iter_close_container (iter, &subiter))
+ goto out;
+
+ ret = TRUE;
+ out:
+ g_free (variant_sig);
+ return ret;
+}
+
+static DBusGValueMarshalFunc
+get_type_marshaller (GType type)
+{
+ DBusGTypeMarshalData *typedata;
+
+ typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
+ if (typedata == NULL)
+ {
+ if (g_type_is_a (type, G_TYPE_ARRAY))
+ return marshal_valuearray;
+ if (dbus_g_type_is_collection (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;
+ }
+ g_assert (typedata->vtable);
+ return typedata->vtable->marshaller;
+}
+
+typedef struct
+{
+ DBusMessageIter *iter;
+ DBusGValueMarshalFunc marshaller;
+ gboolean err;
+} DBusGValueCollectionMarshalData;
+
+static void
+collection_marshal_iterator (const GValue *eltval,
+ gpointer user_data)
+{
+ DBusGValueCollectionMarshalData *data = user_data;
+
+ if (data->err)
+ return;
+
+ if (!data->marshaller (data->iter, eltval))
+ data->err = TRUE;
+}
+
+static gboolean
+marshal_collection (DBusMessageIter *iter,
+ const GValue *value)
+{
+ GType coltype;
+ GType subtype;
+
+ coltype = G_VALUE_TYPE (value);
+ subtype = dbus_g_type_get_collection_specialization (coltype);
+
+ if (_dbus_g_type_is_fixed (subtype))
+ return marshal_collection_array (iter, value);
+ else
+ return marshal_collection_ptrarray (iter, value);
+}
+
+static gboolean
+marshal_collection_ptrarray (DBusMessageIter *iter,
+ const GValue *value)
+{
+ GType coltype;
+ GType elt_gtype;
+ DBusGValueCollectionMarshalData data;
+ DBusMessageIter subiter;
+ char *elt_sig;
+
+ coltype = G_VALUE_TYPE (value);
+ elt_gtype = dbus_g_type_get_collection_specialization (coltype);
+ data.marshaller = get_type_marshaller (elt_gtype);
+ if (!data.marshaller)
+ return FALSE;
+
+ 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;
+ }
+ g_assert (g_variant_is_signature (elt_sig));
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_ARRAY,
+ elt_sig,
+ &subiter))
+ oom ();
+
+ g_free (elt_sig);
+
+ data.iter = &subiter;
+ data.err = FALSE;
+
+ dbus_g_type_collection_value_iterate (value,
+ collection_marshal_iterator,
+ &data);
+
+ if (data.err)
+ {
+ dbus_message_iter_abandon_container (iter, &subiter);
+ return FALSE;
+ }
+
+ return dbus_message_iter_close_container (iter, &subiter);
+}
+
+/* If any of these assertions are violated, then marshal_collection_array
+ * is buggy for that type. dbus_g_value_basic_array_parse_variant() has
+ * general size-conversion code, if needed. */
+G_STATIC_ASSERT (sizeof (dbus_bool_t) == sizeof (gboolean));
+G_STATIC_ASSERT (sizeof (dbus_int32_t) == sizeof (gint));
+G_STATIC_ASSERT (sizeof (dbus_uint32_t) == sizeof (guint));
+/* These should be true regardless, but just for completeness... */
+G_STATIC_ASSERT (sizeof (dbus_int64_t) == sizeof (gint64));
+G_STATIC_ASSERT (sizeof (dbus_uint64_t) == sizeof (guint64));
+G_STATIC_ASSERT (sizeof (double) == sizeof (gdouble));
+
+static gboolean
+marshal_collection_array (DBusMessageIter *iter,
+ const GValue *value)
+{
+ GType elt_gtype;
+ DBusMessageIter subiter;
+ GArray *array;
+ char *subsignature_str;
+
+ array = g_value_get_boxed (value);
+ g_return_val_if_fail (array != NULL, FALSE);
+
+ 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);
+ if (!subsignature_str)
+ {
+ g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
+ return FALSE;
+ }
+ g_assert (g_variant_is_signature (subsignature_str));
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_ARRAY,
+ subsignature_str,
+ &subiter))
+ oom ();
+
+ /* TODO - This assumes that basic values are the same size
+ * is this always true? If it is we can probably avoid
+ * a lot of the overhead in _marshal_basic_instance...
+ */
+ if (!dbus_message_iter_append_fixed_array (&subiter,
+ subsignature_str[0],
+ &(array->data),
+ array->len))
+ {
+ g_critical ("Unable to serialize %u GArray members as signature %s "
+ "(OOM or invalid boolean value?)", array->len, subsignature_str);
+
+ g_free (subsignature_str);
+ dbus_message_iter_abandon_container (iter, &subiter);
+ return FALSE;
+ }
+
+ g_free (subsignature_str);
+ return dbus_message_iter_close_container (iter, &subiter);
+}
+
+gboolean
+_dbus_gvalue_marshal (DBusMessageIter *iter,
+ const GValue *value)
+{
+ GType gtype;
+ DBusGValueMarshalFunc marshaller;
+
+ gtype = G_VALUE_TYPE (value);
+
+ marshaller = get_type_marshaller (gtype);
+ if (marshaller == NULL)
+ return FALSE;
+ return marshaller (iter, value);
+}
+
+#ifdef DBUS_BUILD_TESTS
+
+static void
+assert_type_maps_to (GType gtype, const char *expected_sig)
+{
+ char *sig;
+ sig = _dbus_gtype_to_signature (gtype);
+ g_assert_nonnull (sig);
+ g_assert_cmpstr (expected_sig, ==, sig);
+ g_free (sig);
+}
+
+static void
+assert_signature_maps_to (const char *sig, GType expected_gtype)
+{
+ g_assert_cmpuint (_dbus_gtype_from_signature (sig, TRUE), ==, expected_gtype);
+}
+
+static void
+assert_bidirectional_mapping (GType gtype, const char *expected_sig)
+{
+ assert_type_maps_to (gtype, expected_sig);
+ assert_signature_maps_to (expected_sig, gtype);
+}
+
+/*
+ * Unit test for general glib stuff
+ * Returns: %TRUE on success.
+ */
+gboolean
+_dbus_gvalue_test (const char *test_data_dir)
+{
+ GType type;
+ GType rectype;
+
+ g_type_init ();
+ _dbus_g_value_types_init ();
+
+ assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING);
+ assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
+ assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
+
+ 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),
+ 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 );
+
+ rectype = dbus_g_type_get_collection ("GArray", G_TYPE_UINT);
+ g_assert_cmpuint (rectype, !=, G_TYPE_INVALID);
+ g_assert_cmpstr (g_type_name (rectype), ==, "GArray_guint_");
+
+ type = _dbus_gtype_from_signature ("au", TRUE);
+ g_assert_cmpuint (type, ==, rectype);
+
+ rectype = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING);
+ g_assert_cmpuint (rectype, !=, G_TYPE_INVALID);
+ g_assert_cmpstr (g_type_name (rectype), ==, "GHashTable_gchararray+gchararray_");
+
+ type = _dbus_gtype_from_signature ("a{ss}", TRUE);
+ g_assert_cmpuint (type, ==, rectype);
+
+ type = _dbus_gtype_from_signature ("o", FALSE);
+ g_assert_cmpuint (type, ==, DBUS_TYPE_G_OBJECT_PATH);
+ type = _dbus_gtype_from_signature ("o", TRUE);
+ g_assert_cmpuint (type, ==, DBUS_TYPE_G_OBJECT_PATH);
+
+ type = _dbus_gtype_from_signature ("g", TRUE);
+ g_assert_cmpuint (type, ==, DBUS_TYPE_G_SIGNATURE);
+
+ return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
Index: dbus-glib-0.112-new/dbus
===================================================================
--- dbus-glib-0.112-new/dbus (nonexistent)
+++ dbus-glib-0.112-new/dbus (revision 5)
Property changes on: dbus-glib-0.112-new/dbus
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: dbus-glib-0.112-new
===================================================================
--- dbus-glib-0.112-new (nonexistent)
+++ dbus-glib-0.112-new (revision 5)
Property changes on: dbus-glib-0.112-new
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: file.list
===================================================================
--- file.list (nonexistent)
+++ file.list (revision 5)
@@ -0,0 +1,3 @@
+dbus-glib-0.112/dbus/dbus-binding-tool-glib.c
+dbus-glib-0.112/dbus/dbus-gvalue-utils.c
+dbus-glib-0.112/dbus/dbus-gvalue.c
Index: .
===================================================================
--- . (nonexistent)
+++ . (revision 5)
Property changes on: .
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~