[Telepathy-commits] [telepathy-mission-control/master] Alternative way to update properties
Alberto Mardegan
alberto.mardegan at nokia.com
Wed Nov 12 00:50:56 PST 2008
Instead of iterating the properties, only look-up those that we recognize.
Move type-checking in a separate function, so that the update function gets
simpler.
---
libmcclient/mc-dispatch-operation.c | 143 ++++++++++++++++++++++-------------
1 files changed, 90 insertions(+), 53 deletions(-)
diff --git a/libmcclient/mc-dispatch-operation.c b/libmcclient/mc-dispatch-operation.c
index 4e73799..1524b02 100644
--- a/libmcclient/mc-dispatch-operation.c
+++ b/libmcclient/mc-dispatch-operation.c
@@ -83,6 +83,16 @@ enum
PROP_PROPERTIES,
};
+/* if this turns out to work well, we can move this definition to a common
+ * header and use it in every module */
+typedef struct {
+ gchar *name;
+ gchar *dbus_signature;
+ void (*update_property) (const gchar *name, const GValue *value,
+ gpointer props_struct);
+} McProperty;
+
+
static void
mc_dispatch_operation_init (McDispatchOperation *operation)
{
@@ -111,7 +121,7 @@ operation_props_free (McDispatchOperationProps *props)
}
static inline GList *
-create_channels_prop (GValue *value)
+create_channels_prop (const GValue *value)
{
GList *list = NULL;
GPtrArray *channels;
@@ -132,69 +142,96 @@ create_channels_prop (GValue *value)
return list;
}
-static void
-update_property (gpointer key, gpointer ht_value, gpointer user_data)
+void
+set_connection (const gchar *name, const GValue *value, gpointer props_struct)
{
- McDispatchOperation *operation = user_data;
- McDispatchOperationProps *props = operation->priv->props;
- GValue *value = ht_value;
- const gchar *name = key;
+ McDispatchOperationProps *props = props_struct;
+ g_free (props->connection);
+ props->connection = g_value_dup_boxed (value);
+}
- if (strcmp (name, "Connection") == 0)
- {
- g_free (props->connection);
- if (G_LIKELY (G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH)))
- props->connection = g_value_dup_boxed (value);
- else
- {
- g_warning ("%s: %s is a %s, expecting object path",
- G_STRFUNC, name, G_VALUE_TYPE_NAME (value));
- props->connection = NULL;
- }
- }
- else if (strcmp (name, "Account") == 0)
- {
- g_free (props->account);
- if (G_LIKELY (G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH)))
- props->account = g_value_dup_boxed (value);
- else
- {
- g_warning ("%s: %s is a %s, expecting object path",
- G_STRFUNC, name, G_VALUE_TYPE_NAME (value));
- props->account = NULL;
- }
- }
- else if (strcmp (name, "Channels") == 0)
- {
- g_list_foreach (props->channels, (GFunc)mc_channel_details_free, NULL);
- g_list_free (props->channels);
- if (G_LIKELY (G_VALUE_HOLDS (value,
- MC_ARRAY_TYPE_CHANNEL_DETAILS_LIST)))
- {
- props->channels = create_channels_prop (value);
- }
- else
- {
- g_warning ("%s: %s is a %s, expecting ChannelDetailList",
- G_STRFUNC, name, G_VALUE_TYPE_NAME (value));
- props->channels = NULL;
- }
- }
- else if (strcmp (name, "PossibleHandlers") == 0)
- {
- g_strfreev (props->possible_handlers);
- props->possible_handlers = g_value_dup_boxed (value);
- }
+void
+set_account (const gchar *name, const GValue *value, gpointer props_struct)
+{
+ McDispatchOperationProps *props = props_struct;
+ g_free (props->account);
+ props->account = g_value_dup_boxed (value);
+}
+
+void
+set_channels (const gchar *name, const GValue *value, gpointer props_struct)
+{
+ McDispatchOperationProps *props = props_struct;
+ g_list_foreach (props->channels, (GFunc)mc_channel_details_free, NULL);
+ g_list_free (props->channels);
+ props->channels = create_channels_prop (value);
+}
+
+void
+set_possible_handlers (const gchar *name, const GValue *value,
+ gpointer props_struct)
+{
+ McDispatchOperationProps *props = props_struct;
+ g_strfreev (props->possible_handlers);
+ props->possible_handlers = g_value_dup_boxed (value);
+}
+
+static const McProperty dispatch_operation_props[] =
+{
+ { "Connection", "o", set_connection },
+ { "Account", "o", set_account },
+ { "Channels", "a(oa{sv})", set_channels },
+ { "PossibleHandlers", "as", set_possible_handlers },
+ { NULL, NULL, NULL }
+};
+
+static GType
+gtype_from_dbus_signature (const gchar *signature)
+{
+ /* dbus-glib's functions that create the GTypes are implemented using a
+ * lookup table, so that if the sub-component types are the same, the same
+ * GType is returned.
+ * So here it should be safe to use any of the functions that return the
+ * desired type */
+ if (strcmp (signature, "o") == 0)
+ return DBUS_TYPE_G_OBJECT_PATH;
+ if (strcmp (signature, "a(oa{sv})") == 0)
+ return MC_ARRAY_TYPE_CHANNEL_DETAILS_LIST;
+ if (strcmp (signature, "as") == 0)
+ return G_TYPE_STRV;
+ g_warning ("%s: Type %s not mapped", G_STRFUNC, signature);
+ return G_TYPE_INVALID;
}
static void
create_operation_props (McDispatchOperation *operation, GHashTable *properties)
{
McDispatchOperationProps *props;
+ const McProperty *prop;
props = g_slice_new0 (McDispatchOperationProps);
operation->priv->props = props;
- g_hash_table_foreach (properties, update_property, operation);
+
+ for (prop = dispatch_operation_props; prop->name != NULL; prop++)
+ {
+ GValue *value;
+ GType type;
+
+ value = g_hash_table_lookup (properties, prop->name);
+ if (!value) continue;
+
+ type = gtype_from_dbus_signature (prop->dbus_signature);
+ if (G_LIKELY (G_VALUE_HOLDS (value, type)))
+ {
+ prop->update_property (prop->name, value, props);
+ }
+ else
+ {
+ g_warning ("%s: %s is a %s, expecting %s",
+ G_STRFUNC, prop->name,
+ G_VALUE_TYPE_NAME (value), g_type_name (type));
+ }
+ }
}
static void
--
1.5.6.5
More information about the Telepathy-commits
mailing list