[telepathy-gabble/master] Intern feature namespaces in a global string pool
Simon McVittie
simon.mcvittie at collabora.co.uk
Tue Sep 8 04:10:02 PDT 2009
We already have a reference-counted string pool - it's called
TpDynamicHandleRepo! Accordingly, use one (shared between all connections
for maximum re-use) to intern namespaces, and reimplement
GabbleCapabilitySet as a TpHandleSet.
---
src/capabilities.c | 117 ++++++++++++++++++++++++++++++++++---------------
src/capabilities.h | 3 +
src/connection.c | 4 ++
tests/test-presence.c | 4 ++
4 files changed, 93 insertions(+), 35 deletions(-)
diff --git a/src/capabilities.c b/src/capabilities.c
index d21cef6..52b7848 100644
--- a/src/capabilities.c
+++ b/src/capabilities.c
@@ -26,6 +26,8 @@
#include <telepathy-glib/interfaces.h>
#include <telepathy-glib/channel-manager.h>
+#include <telepathy-glib/handle-repo.h>
+#include <telepathy-glib/handle-repo-dynamic.h>
#define DEBUG_FLAG GABBLE_DEBUG_PRESENCE
@@ -141,8 +143,43 @@ omits_content_creators (LmMessageNode *identity)
}
}
+gsize feature_handles_refcount = 0;
+static TpHandleRepoIface *feature_handles = NULL;
+
+void
+gabble_capabilities_init (GabbleConnection *conn)
+{
+ DEBUG ("%p", conn);
+
+ if (feature_handles_refcount++ == 0)
+ {
+ g_assert (feature_handles == NULL);
+ /* TpDynamicHandleRepo wants a handle type, which isn't relevant here
+ * (we're just using it as a string pool). Use an arbitrary handle type
+ * to shut it up. */
+ feature_handles = tp_dynamic_handle_repo_new (TP_HANDLE_TYPE_CONTACT,
+ NULL, NULL);
+ }
+
+ g_assert (feature_handles != NULL);
+}
+
+void
+gabble_capabilities_finalize (GabbleConnection *conn)
+{
+ DEBUG ("%p", conn);
+
+ g_assert (feature_handles_refcount > 0);
+
+ if (--feature_handles_refcount == 0)
+ {
+ g_object_unref (feature_handles);
+ feature_handles = NULL;
+ }
+}
+
struct _GabbleCapabilitySet {
- GPtrArray *strings;
+ TpHandleSet *handles;
};
GabblePresenceCapabilities
@@ -151,9 +188,12 @@ capabilities_parse (GabbleCapabilitySet *cap_set,
{
GabblePresenceCapabilities ret = PRESENCE_CAP_NONE;
const gchar *var;
- guint j;
const Feature *i;
NodeIter ni;
+ TpIntSetIter iter;
+
+ g_return_val_if_fail (cap_set != NULL, 0);
+ g_return_val_if_fail (query_result != NULL, 0);
/* special case: OMITS_CONTENT_CREATOR looks at the software version,
* not the actual features (sad face) */
@@ -165,9 +205,11 @@ capabilities_parse (GabbleCapabilitySet *cap_set,
ret |= PRESENCE_CAP_JINGLE_OMITS_CONTENT_CREATOR;
}
- for (j = 0; j < cap_set->strings->len; j++)
+ tp_intset_iter_init (&iter, tp_handle_set_peek (cap_set->handles));
+
+ while (tp_intset_iter_next (&iter))
{
- var = g_ptr_array_index (cap_set->strings, j);
+ var = tp_handle_inspect (feature_handles, iter.element);
for (i = self_advertised_features; i->ns != NULL; i++)
{
@@ -228,7 +270,8 @@ gabble_capability_set_new (void)
{
GabbleCapabilitySet *ret = g_slice_new0 (GabbleCapabilitySet);
- ret->strings = g_ptr_array_new ();
+ g_assert (feature_handles != NULL);
+ ret->handles = tp_handle_set_new (feature_handles);
return ret;
}
@@ -296,37 +339,35 @@ void
gabble_capability_set_update (GabbleCapabilitySet *target,
const GabbleCapabilitySet *source)
{
- guint i;
-
g_return_if_fail (target != NULL);
g_return_if_fail (source != NULL);
- for (i = 0; i < source->strings->len; i++)
- gabble_capability_set_add (target, g_ptr_array_index (source->strings, i));
+ tp_handle_set_update (target->handles, tp_handle_set_peek (source->handles));
}
void
gabble_capability_set_add (GabbleCapabilitySet *caps,
const gchar *cap)
{
+ TpHandle handle;
+
g_return_if_fail (caps != NULL);
g_return_if_fail (cap != NULL);
- if (!gabble_capability_set_has (caps, cap))
- g_ptr_array_add (caps->strings, g_strdup (cap));
+ handle = tp_handle_ensure (feature_handles, cap, NULL, NULL);
+
+ tp_handle_set_add (caps->handles, handle);
+ tp_handle_unref (feature_handles, handle);
}
void
gabble_capability_set_clear (GabbleCapabilitySet *caps)
{
- guint i;
-
g_return_if_fail (caps != NULL);
- for (i = 0; i < caps->strings->len; i++)
- g_free (g_ptr_array_index (caps->strings, i));
-
- g_ptr_array_set_size (caps->strings, 0);
+ /* There is no tp_handle_set_clear, so do the next best thing */
+ tp_handle_set_destroy (caps->handles);
+ caps->handles = tp_handle_set_new (feature_handles);
}
void
@@ -334,8 +375,7 @@ gabble_capability_set_free (GabbleCapabilitySet *caps)
{
g_return_if_fail (caps != NULL);
- gabble_capability_set_clear (caps);
- g_ptr_array_free (caps->strings, TRUE);
+ tp_handle_set_destroy (caps->handles);
g_slice_free (GabbleCapabilitySet, caps);
}
@@ -343,40 +383,47 @@ gboolean
gabble_capability_set_has (const GabbleCapabilitySet *caps,
const gchar *cap)
{
- guint i;
+ TpHandle handle;
g_return_val_if_fail (caps != NULL, FALSE);
g_return_val_if_fail (cap != NULL, FALSE);
- for (i = 0; i < caps->strings->len; i++)
- if (!tp_strdiff (g_ptr_array_index (caps->strings, i), cap))
- return TRUE;
+ handle = tp_handle_lookup (feature_handles, cap, NULL, NULL);
- return FALSE;
+ if (handle == 0)
+ {
+ /* nobody in the whole CM has this capability */
+ return FALSE;
+ }
+
+ return tp_handle_set_is_member (caps->handles, handle);
}
gboolean
gabble_capability_set_equals (const GabbleCapabilitySet *a,
const GabbleCapabilitySet *b)
{
- guint i;
-
g_return_val_if_fail (a != NULL, FALSE);
g_return_val_if_fail (b != NULL, FALSE);
- if (a->strings->len != b->strings->len)
- return FALSE;
-
- for (i = 0; i < a->strings->len; i++)
- if (!gabble_capability_set_has (b, g_ptr_array_index (a->strings, i)))
- return FALSE;
-
- return TRUE;
+ return tp_intset_is_equal (tp_handle_set_peek (a->handles),
+ tp_handle_set_peek (b->handles));
}
void
gabble_capability_set_foreach (const GabbleCapabilitySet *caps,
GFunc func, gpointer user_data)
{
- g_ptr_array_foreach (caps->strings, func, user_data);
+ TpIntSetIter iter;
+
+ g_return_if_fail (caps != NULL);
+ g_return_if_fail (func != NULL);
+
+ tp_intset_iter_init (&iter, tp_handle_set_peek (caps->handles));
+
+ while (tp_intset_iter_next (&iter))
+ {
+ func ((gchar *) tp_handle_inspect (feature_handles, iter.element),
+ user_data);
+ }
}
diff --git a/src/capabilities.h b/src/capabilities.h
index aafe364..491eba4 100644
--- a/src/capabilities.h
+++ b/src/capabilities.h
@@ -113,5 +113,8 @@ struct _CapabilityConversionData
extern const CapabilityConversionData capabilities_conversions[];
+void gabble_capabilities_init (GabbleConnection *conn);
+void gabble_capabilities_finalize (GabbleConnection *conn);
+
#endif /* __GABBLE_CAPABILITIES__H__ */
diff --git a/src/connection.c b/src/connection.c
index da6f020..d4a3896 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -357,6 +357,8 @@ gabble_connection_init (GabbleConnection *self)
priv->caps_serial = 1;
priv->port = 5222;
+
+ gabble_capabilities_init (self);
}
static void
@@ -942,6 +944,8 @@ gabble_connection_finalize (GObject *object)
conn_presence_finalize (self);
+ gabble_capabilities_finalize (self);
+
G_OBJECT_CLASS (gabble_connection_parent_class)->finalize (object);
}
diff --git a/tests/test-presence.c b/tests/test-presence.c
index 2fac88d..0c6d333 100644
--- a/tests/test-presence.c
+++ b/tests/test-presence.c
@@ -16,6 +16,7 @@ int main (int argc, char **argv)
GabbleCapabilitySet *cap_set;
g_type_init ();
+ gabble_capabilities_init (NULL);
presence = gabble_presence_new ();
g_assert (GABBLE_PRESENCE_OFFLINE == presence->status);
@@ -174,6 +175,9 @@ int main (int argc, char **argv)
g_free (dump);
g_object_unref (presence);
+
+ gabble_capabilities_finalize (NULL);
+
return 0;
}
--
1.5.6.5
More information about the telepathy-commits
mailing list