summaryrefslogtreecommitdiff
path: root/telepathy-glib/handle-repo-static.c
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2007-04-19 17:35:17 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2007-04-19 17:35:17 +0000
commit05b3d77a6ceaf9142e0dee8bf52e7637d5823bdd (patch)
treeae7da2dc08fb4c3aa1c6b09ffa1c57d2d3adf24a /telepathy-glib/handle-repo-static.c
parent90720ee40eb30e2b1c9aa90501391d3a0a411250 (diff)
downloadtelepathy-glib-05b3d77a6ceaf9142e0dee8bf52e7637d5823bdd.tar.gz
Move contents of lib/ into root directory
20070419173517-53eee-d91a15d77882d6839193c1f77be4f88803b48f58.gz
Diffstat (limited to 'telepathy-glib/handle-repo-static.c')
-rw-r--r--telepathy-glib/handle-repo-static.c338
1 files changed, 338 insertions, 0 deletions
diff --git a/telepathy-glib/handle-repo-static.c b/telepathy-glib/handle-repo-static.c
new file mode 100644
index 000000000..58304a343
--- /dev/null
+++ b/telepathy-glib/handle-repo-static.c
@@ -0,0 +1,338 @@
+/*
+ * handle-repo-static.c - mechanism to store and retrieve handles on a
+ * connection (implementation for handle types with a fixed list of possible
+ * handles)
+ *
+ * Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright (C) 2007 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:handle-repo-static
+ * @title: TpStaticHandleRepo
+ * @short_description: handle repository implementation with a fixed, static
+ * set of handle names
+ * @see_also: TpHandleRepoIface, TpDynamicHandleRepo
+ *
+ * A static handle repository has a fixed, static set of allowed names;
+ * these handles can never be destroyed, and no more can be created, so
+ * no reference counting is performed.
+ *
+ * The #TpHandleRepoIface:handle-type property must be set at construction
+ * time.
+ *
+ * Most connection managers will use this for handles of type
+ * %TP_HANDLE_TYPE_CONTACT_LIST.
+ */
+
+#include <telepathy-glib/handle-repo-static.h>
+
+#include <string.h>
+
+#include <telepathy-glib/internal-handle-repo.h>
+
+enum
+{
+ PROP_HANDLE_TYPE = 1,
+ PROP_HANDLE_NAMES,
+};
+
+struct _TpStaticHandleRepoClass {
+ GObjectClass parent_class;
+};
+
+struct _TpStaticHandleRepo {
+ GObject parent;
+ TpHandleType handle_type;
+ TpHandle last_handle;
+ gchar **handle_names;
+ GData **datalists;
+};
+
+static void static_repo_iface_init (gpointer g_iface,
+ gpointer iface_data);
+
+G_DEFINE_TYPE_WITH_CODE (TpStaticHandleRepo, tp_static_handle_repo,
+ G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_HANDLE_REPO_IFACE,
+ static_repo_iface_init));
+
+static void
+tp_static_handle_repo_init (TpStaticHandleRepo *self)
+{
+ self->handle_type = 0;
+ self->last_handle = 0;
+ self->handle_names = NULL;
+ self->datalists = NULL;
+}
+
+static void
+static_finalize (GObject *object)
+{
+ TpStaticHandleRepo *self = TP_STATIC_HANDLE_REPO (object);
+ guint i;
+
+ if (self->datalists)
+ {
+ for (i = 0; i < self->last_handle; i++)
+ {
+ g_datalist_clear (self->datalists + i);
+ }
+ }
+
+ g_strfreev (self->handle_names);
+
+ G_OBJECT_CLASS (tp_static_handle_repo_parent_class)->finalize (object);
+}
+
+static void
+static_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TpStaticHandleRepo *self = TP_STATIC_HANDLE_REPO (object);
+
+ switch (property_id)
+ {
+ case PROP_HANDLE_TYPE:
+ g_value_set_uint (value, self->handle_type);
+ break;
+ case PROP_HANDLE_NAMES:
+ g_value_set_boxed (value, g_strdupv (self->handle_names));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+static_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TpStaticHandleRepo *self = TP_STATIC_HANDLE_REPO (object);
+ TpHandle i;
+
+ switch (property_id)
+ {
+ case PROP_HANDLE_TYPE:
+ self->handle_type = g_value_get_uint (value);
+ break;
+
+ case PROP_HANDLE_NAMES:
+
+ if (self->datalists)
+ {
+ for (i = 0; i < self->last_handle; i++)
+ {
+ g_datalist_clear (self->datalists + i);
+ }
+ }
+
+ g_strfreev (self->handle_names);
+ self->handle_names = g_strdupv (g_value_get_boxed (value));
+ i = 0;
+ while (self->handle_names[i] != NULL)
+ {
+ i++;
+ }
+ self->last_handle = i;
+
+ g_free (self->datalists);
+ self->datalists = NULL;
+
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+tp_static_handle_repo_class_init (TpStaticHandleRepoClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GParamSpec *param_spec;
+
+ object_class->get_property = static_get_property;
+ object_class->set_property = static_set_property;
+ object_class->finalize = static_finalize;
+
+ g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
+ "handle-type");
+ param_spec = g_param_spec_boxed ("handle-names", "Handle names",
+ "The static set of handle names supported by this repo.",
+ G_TYPE_STRV,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB);
+ g_object_class_install_property (object_class, PROP_HANDLE_NAMES,
+ param_spec);
+}
+
+static gboolean
+static_handle_is_valid (TpHandleRepoIface *irepo,
+ TpHandle handle,
+ GError **error)
+{
+ TpStaticHandleRepo *self = TP_STATIC_HANDLE_REPO (irepo);
+
+ if (handle <= 0 || handle > self->last_handle)
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "handle %u is not a valid %s handle (type %u)",
+ handle, tp_handle_type_to_string (self->handle_type),
+ self->handle_type);
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+static gboolean
+static_handles_are_valid (TpHandleRepoIface *irepo, const GArray *handles,
+ gboolean allow_zero, GError **error)
+{
+ guint i;
+
+ g_return_val_if_fail (handles != NULL, FALSE);
+
+ for (i = 0; i < handles->len; i++)
+ {
+ TpHandle handle = g_array_index (handles, TpHandle, i);
+
+ if (handle == 0 && allow_zero)
+ continue;
+
+ if (!static_handle_is_valid (irepo, handle, error))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+static_ref_or_unref_handle (TpHandleRepoIface *self, TpHandle handle)
+{
+ /* nothing to do, handles in this repo are permanent */
+}
+
+static gboolean
+static_client_hold_or_release_handle (TpHandleRepoIface *self,
+ const gchar *client_name,
+ TpHandle handle,
+ GError **error)
+{
+ /* nothing to do, handles in this repo are permanent */
+ return TRUE;
+}
+
+static const char *
+static_inspect_handle (TpHandleRepoIface *irepo, TpHandle handle)
+{
+ TpStaticHandleRepo *self = TP_STATIC_HANDLE_REPO (irepo);
+
+ if (handle <= 0 || handle > self->last_handle)
+ return NULL;
+
+ return self->handle_names[handle-1];
+}
+
+static TpHandle
+static_lookup_handle (TpHandleRepoIface *irepo,
+ const char *id,
+ gpointer context,
+ GError **error)
+{
+ TpStaticHandleRepo *self = TP_STATIC_HANDLE_REPO (irepo);
+ guint i;
+
+ for (i = 0; i < self->last_handle; i++)
+ {
+ if (!strcmp (self->handle_names[i], id))
+ return (TpHandle) i + 1;
+ }
+
+ g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ "'%s' is not one of the valid handles", id);
+ return 0;
+}
+
+
+static void
+static_set_qdata (TpHandleRepoIface *repo, TpHandle handle,
+ GQuark key_id, gpointer data, GDestroyNotify destroy)
+{
+ TpStaticHandleRepo *self = TP_STATIC_HANDLE_REPO (repo);
+ guint i;
+
+ g_return_if_fail (handle > 0);
+ g_return_if_fail (handle <= self->last_handle);
+
+ if (!self->datalists)
+ {
+ self->datalists = g_new (GData *, self->last_handle);
+ for (i = 0; i < self->last_handle; i++)
+ {
+ g_datalist_init (self->datalists + i);
+ }
+ }
+
+ g_datalist_id_set_data_full (self->datalists + handle - 1, key_id, data,
+ destroy);
+}
+
+static gpointer
+static_get_qdata (TpHandleRepoIface *repo, TpHandle handle,
+ GQuark key_id)
+{
+ TpStaticHandleRepo *self = TP_STATIC_HANDLE_REPO (repo);
+
+ g_return_val_if_fail (handle > 0, NULL);
+ g_return_val_if_fail (handle <= self->last_handle, NULL);
+
+ /* if we have no datalists that's not a bug - it means nobody has called
+ * static_set_qdata yet */
+ if (!self->datalists)
+ return NULL;
+
+ return g_datalist_id_get_data (self->datalists + handle - 1, key_id);
+}
+
+static void
+static_repo_iface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ TpHandleRepoIfaceClass *klass = (TpHandleRepoIfaceClass *) g_iface;
+
+ klass->handle_is_valid = static_handle_is_valid;
+ klass->handles_are_valid = static_handles_are_valid;
+ klass->ref_handle = static_ref_or_unref_handle;
+ klass->unref_handle = static_ref_or_unref_handle;
+ klass->client_hold_handle = static_client_hold_or_release_handle;
+ klass->client_release_handle = static_client_hold_or_release_handle;
+ klass->inspect_handle = static_inspect_handle;
+ /* this repo is static, so lookup and ensure are identical */
+ klass->lookup_handle = static_lookup_handle;
+ klass->ensure_handle = static_lookup_handle;
+ klass->set_qdata = static_set_qdata;
+ klass->get_qdata = static_get_qdata;
+}