diff -r 000000000000 -r d0f3a028347a telepathygabble/src/handle-set.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telepathygabble/src/handle-set.c Tue Feb 02 01:10:06 2010 +0200 @@ -0,0 +1,274 @@ +/* + * handle-set.c - a set which refs a handle when inserted + * + * Copyright (C) 2005,2006 Collabora Ltd. + * + * + * 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 + * + */ +#include +#include "gintset.h" +#include "handles.h" + +#include "handle-set.h" + +struct _GabbleHandleSet +{ + GabbleHandleRepo *repo; + GIntSet *intset; + TpHandleType type; +}; + +/** + * handle_set_new: + * @repo: #GabbleHandleRepo that holds the handles to be reffed by this set + * + * Creates a new #GabbleHandleSet + * + * Returns: A new #GabbleHandleSet + */ + +GabbleHandleSet * +handle_set_new (GabbleHandleRepo *repo, TpHandleType type) +{ + GabbleHandleSet *set = g_new(GabbleHandleSet, 1); + set->intset = g_intset_new(); + set->repo = repo; + set->type = type; + + return set; +} + +static void +freer (GabbleHandleSet *set, GabbleHandle handle, gpointer userdata) +{ + handle_set_remove (set, handle); +} + +/** + * handle_set_destroy: + * @set:#GabbleHandleSet to destroy + * + * Delete a #GabbleHandleSet and unreference any handles that it holds + */ + +void +handle_set_destroy (GabbleHandleSet *set) +{ + handle_set_foreach (set, freer, NULL); + g_intset_destroy (set->intset); + g_free (set); +} + +/** + * handle_set_peek: + * @set:#GabbleHandleSet to peek at + * + * Get the underlying GIntSet used by this GabbleHandleSet + */ +GIntSet * +handle_set_peek (GabbleHandleSet *set) +{ + return set->intset; +} + +/** + * handle_set_add: + * @set: #GabbleHandleSet to add this handle to + * @handle: handle to add + * + * Add a handle to a #GabbleHandleSet,and reference it in the attched + * #GabbleHandleRepo + * + */ + +void +handle_set_add (GabbleHandleSet *set, GabbleHandle handle) +{ + g_return_if_fail (set != NULL); + g_return_if_fail (handle != 0); + + if (!g_intset_is_member(set->intset, handle)) + { + g_return_if_fail (gabble_handle_ref (set->repo, set->type, handle)); + + g_intset_add (set->intset, handle); + } +} + +/** + * handle_set_remove: + * @set: #GabbleHandleSet to remove this handle from + * @handle: handle to remove + * @type: type of handle + * + * Remove a handle to a #GabbleHandleSet,and unreference it in the attched + * #GabbleHandleRepo + * + * Returns: FALSE if the (handle,type) pair was invalid, or was not in this set + */ + + +gboolean +handle_set_remove (GabbleHandleSet *set, GabbleHandle handle) +{ + g_return_val_if_fail (set != NULL, FALSE); + g_return_val_if_fail (handle != 0, FALSE); + + if (g_intset_is_member(set->intset, handle)) + { + g_return_val_if_fail (gabble_handle_unref (set->repo, set->type, handle), FALSE); + + g_intset_remove (set->intset, handle); + return TRUE; + } + + return FALSE; +} + +/** + * handle_set_is_member: + * @set: A #GabbleHandleSet + * @handle: handle to check + * @type: type of handle + * + * Check if the (handle,type) pair is in this set + * + * Returns: TRUE if the (handle,type) pair is in this repo + * + */ + +gboolean +handle_set_is_member (GabbleHandleSet *set, GabbleHandle handle) +{ + return g_intset_is_member(set->intset, handle); +} + +typedef struct __foreach_data +{ + GabbleHandleSet *set; + GabbleHandleFunc func; + gpointer userdata; +} _foreach_data; + +static void +foreach_helper(guint i, gpointer userdata) +{ + _foreach_data *data = (_foreach_data*) userdata; + + data->func(data->set, i, data->userdata); +} + +void +handle_set_foreach (GabbleHandleSet *set, GabbleHandleFunc func, gpointer userdata) +{ + _foreach_data data; /*= {set, func, userdata};*/ + data.set = set; + data.func = func; + data.userdata = userdata; + g_intset_foreach (set->intset, foreach_helper, &data); +} + + +int +handle_set_size (GabbleHandleSet *set) +{ + return g_intset_size (set->intset); +} + +GArray *handle_set_to_array (GabbleHandleSet *set) +{ + g_return_val_if_fail (set != NULL, NULL); + + return g_intset_to_array (set->intset); +} + +static void +ref_one (guint handle, gpointer data) +{ + GabbleHandleSet *set = (GabbleHandleSet *) data; + gabble_handle_ref (set->repo, set->type, handle); +} + +/** + * handle_set_update: + * @set: a #GabbleHandleSet to update + * @add: a #GIntSet of handles to add + * + * Add a set of handles to a handle set, referencing those which are not + * already members. The GIntSet returned must be freed with g_intset_destroy. + * + * Returns: the handles which were added + */ + +GIntSet * +handle_set_update (GabbleHandleSet *set, const GIntSet *add) +{ + GIntSet *ret, *tmp; + + g_return_val_if_fail (set != NULL, NULL); + g_return_val_if_fail (add != NULL, NULL); + + /* reference each of ADD - CURRENT */ + ret = g_intset_difference (add, set->intset); + g_intset_foreach (ret, ref_one, set); + + /* update CURRENT to be the union of CURRENT and ADD */ + tmp = g_intset_union (add, set->intset); + g_intset_destroy (set->intset); + set->intset = tmp; + + return ret; +} + +static void +unref_one (guint handle, gpointer data) +{ + GabbleHandleSet *set = (GabbleHandleSet *) data; + gabble_handle_unref (set->repo, set->type, handle); +} + +/** + * handle_set_difference_update: + * @set: a #GabbleHandleSet to update + * @remove: a #GIntSet of handles to remove + * + * Remove a set of handles from a handle set, dereferencing those which are + * members. The GIntSet returned must be freed with g_intset_destroy. + * + * Returns: the handles which were removed + */ + +GIntSet * +handle_set_difference_update (GabbleHandleSet *set, const GIntSet *remove) +{ + GIntSet *ret, *tmp; + + g_return_val_if_fail (set != NULL, NULL); + g_return_val_if_fail (remove != NULL, NULL); + + /* dereference each of REMOVE n CURRENT */ + ret = g_intset_intersection (remove, set->intset); + g_intset_foreach (ret, unref_one, set); + + /* update CURRENT to be CURRENT - REMOVE */ + tmp = g_intset_difference (set->intset, remove); + g_intset_destroy (set->intset); + set->intset = tmp; + + return ret; +}