telepathygabble/src/handle-set.c
branchRCL_3
changeset 11 3404599e4dda
parent 9 46cc8e302e43
equal deleted inserted replaced
9:46cc8e302e43 11:3404599e4dda
     1 /*
       
     2  * handle-set.c - a set which refs a handle when inserted
       
     3  *
       
     4  * Copyright (C) 2005,2006 Collabora Ltd.
       
     5  *
       
     6  *
       
     7  * This library is free software; you can redistribute it and/or
       
     8  * modify it under the terms of the GNU Lesser General Public License
       
     9  * as published by the Free Software Foundation; either version 2.1 of
       
    10  * the License, or (at your option) any later version.
       
    11  *
       
    12  * This library is distributed in the hope that it will be useful, but
       
    13  * WITHOUT ANY WARRANTY; without even the implied warranty of
       
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       
    15  * Lesser General Public License for more details.
       
    16  *
       
    17  * You should have received a copy of the GNU Lesser General Public
       
    18  * License along with this library; if not, write to the Free Software
       
    19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
       
    20  * 02110-1301 USA
       
    21  *
       
    22  */
       
    23 #include <glib.h>
       
    24 #include "gintset.h"
       
    25 #include "handles.h"
       
    26 
       
    27 #include "handle-set.h"
       
    28 
       
    29 struct _GabbleHandleSet
       
    30 {
       
    31   GabbleHandleRepo *repo;
       
    32   GIntSet *intset;
       
    33   TpHandleType type;
       
    34 };
       
    35 
       
    36 /**
       
    37  * handle_set_new:
       
    38  * @repo: #GabbleHandleRepo that holds the handles to be reffed by this set
       
    39  *
       
    40  * Creates a new #GabbleHandleSet
       
    41  *
       
    42  * Returns: A new #GabbleHandleSet
       
    43  */
       
    44 
       
    45 GabbleHandleSet *
       
    46 handle_set_new (GabbleHandleRepo *repo, TpHandleType type)
       
    47 {
       
    48   GabbleHandleSet *set = g_new(GabbleHandleSet, 1);
       
    49   set->intset = g_intset_new();
       
    50   set->repo = repo;
       
    51   set->type = type;
       
    52 
       
    53   return set;
       
    54 }
       
    55 
       
    56 static void
       
    57 freer (GabbleHandleSet *set, GabbleHandle handle, gpointer userdata)
       
    58 {
       
    59   handle_set_remove (set, handle);
       
    60 }
       
    61 
       
    62 /**
       
    63  * handle_set_destroy:
       
    64  * @set:#GabbleHandleSet to destroy
       
    65  *
       
    66  * Delete a #GabbleHandleSet and unreference any handles that it holds
       
    67  */
       
    68 
       
    69 void
       
    70 handle_set_destroy (GabbleHandleSet *set)
       
    71 {
       
    72   handle_set_foreach (set, freer, NULL);
       
    73   g_intset_destroy (set->intset);
       
    74   g_free (set);
       
    75 }
       
    76 
       
    77 /**
       
    78  * handle_set_peek:
       
    79  * @set:#GabbleHandleSet to peek at
       
    80  *
       
    81  * Get the underlying GIntSet used by this GabbleHandleSet
       
    82  */
       
    83 GIntSet *
       
    84 handle_set_peek (GabbleHandleSet *set)
       
    85 {
       
    86   return set->intset;
       
    87 }
       
    88 
       
    89 /**
       
    90  * handle_set_add:
       
    91  * @set: #GabbleHandleSet to add this handle to
       
    92  * @handle: handle to add
       
    93  *
       
    94  * Add a handle to a #GabbleHandleSet,and reference it in the attched
       
    95  * #GabbleHandleRepo
       
    96  *
       
    97  */
       
    98 
       
    99 void
       
   100 handle_set_add (GabbleHandleSet *set, GabbleHandle handle)
       
   101 {
       
   102   g_return_if_fail (set != NULL);
       
   103   g_return_if_fail (handle != 0);
       
   104 
       
   105   if (!g_intset_is_member(set->intset, handle))
       
   106     {
       
   107       g_return_if_fail (gabble_handle_ref (set->repo, set->type, handle));
       
   108 
       
   109       g_intset_add (set->intset, handle);
       
   110     }
       
   111 }
       
   112 
       
   113 /**
       
   114  * handle_set_remove:
       
   115  * @set: #GabbleHandleSet to remove this handle from
       
   116  * @handle: handle to remove
       
   117  * @type: type of handle
       
   118  *
       
   119  * Remove a handle to a #GabbleHandleSet,and unreference it in the attched
       
   120  * #GabbleHandleRepo
       
   121  *
       
   122  * Returns: FALSE if the (handle,type) pair was invalid, or was not in this set
       
   123  */
       
   124 
       
   125 
       
   126 gboolean
       
   127 handle_set_remove (GabbleHandleSet *set, GabbleHandle handle)
       
   128 {
       
   129   g_return_val_if_fail (set != NULL, FALSE);
       
   130   g_return_val_if_fail (handle != 0, FALSE);
       
   131 
       
   132   if (g_intset_is_member(set->intset, handle))
       
   133     {
       
   134       g_return_val_if_fail (gabble_handle_unref (set->repo, set->type, handle), FALSE);
       
   135 
       
   136       g_intset_remove (set->intset, handle);
       
   137       return TRUE;
       
   138     }
       
   139 
       
   140   return FALSE;
       
   141 }
       
   142 
       
   143 /**
       
   144  * handle_set_is_member:
       
   145  * @set: A #GabbleHandleSet
       
   146  * @handle: handle to check
       
   147  * @type: type of handle
       
   148  *
       
   149  * Check if the (handle,type) pair is in this set
       
   150  *
       
   151  * Returns: TRUE if the (handle,type) pair is in this repo
       
   152  *
       
   153  */
       
   154  
       
   155 gboolean
       
   156 handle_set_is_member (GabbleHandleSet *set, GabbleHandle handle)
       
   157 {
       
   158   return g_intset_is_member(set->intset, handle);
       
   159 }
       
   160 
       
   161 typedef struct __foreach_data
       
   162 {
       
   163   GabbleHandleSet *set;
       
   164   GabbleHandleFunc func;
       
   165   gpointer userdata;
       
   166 } _foreach_data;
       
   167 
       
   168 static void
       
   169 foreach_helper(guint i, gpointer userdata)
       
   170 {
       
   171   _foreach_data *data = (_foreach_data*) userdata;
       
   172 
       
   173   data->func(data->set, i, data->userdata);
       
   174 }
       
   175 
       
   176 void
       
   177 handle_set_foreach (GabbleHandleSet *set, GabbleHandleFunc func, gpointer userdata)
       
   178 {
       
   179   _foreach_data data; /*= {set, func, userdata};*/
       
   180   data.set = set;
       
   181   data.func = func;
       
   182   data.userdata = userdata;
       
   183   g_intset_foreach (set->intset, foreach_helper, &data);
       
   184 }
       
   185 
       
   186 
       
   187 int
       
   188 handle_set_size (GabbleHandleSet *set)
       
   189 {
       
   190   return g_intset_size (set->intset);
       
   191 }
       
   192 
       
   193 GArray *handle_set_to_array (GabbleHandleSet *set)
       
   194 {
       
   195   g_return_val_if_fail (set != NULL, NULL);
       
   196 
       
   197   return g_intset_to_array (set->intset);
       
   198 }
       
   199 
       
   200 static void
       
   201 ref_one (guint handle, gpointer data)
       
   202 {
       
   203   GabbleHandleSet *set = (GabbleHandleSet *) data;
       
   204   gabble_handle_ref (set->repo, set->type, handle);
       
   205 }
       
   206 
       
   207 /**
       
   208  * handle_set_update:
       
   209  * @set: a #GabbleHandleSet to update
       
   210  * @add: a #GIntSet of handles to add
       
   211  *
       
   212  * Add a set of handles to a handle set, referencing those which are not
       
   213  * already members. The GIntSet returned must be freed with g_intset_destroy.
       
   214  *
       
   215  * Returns: the handles which were added
       
   216  */
       
   217 
       
   218 GIntSet *
       
   219 handle_set_update (GabbleHandleSet *set, const GIntSet *add)
       
   220 {
       
   221   GIntSet *ret, *tmp;
       
   222 
       
   223   g_return_val_if_fail (set != NULL, NULL);
       
   224   g_return_val_if_fail (add != NULL, NULL);
       
   225 
       
   226   /* reference each of ADD - CURRENT */
       
   227   ret = g_intset_difference (add, set->intset);
       
   228   g_intset_foreach (ret, ref_one, set);
       
   229 
       
   230   /* update CURRENT to be the union of CURRENT and ADD */
       
   231   tmp = g_intset_union (add, set->intset);
       
   232   g_intset_destroy (set->intset);
       
   233   set->intset = tmp;
       
   234 
       
   235   return ret;
       
   236 }
       
   237 
       
   238 static void
       
   239 unref_one (guint handle, gpointer data)
       
   240 {
       
   241   GabbleHandleSet *set = (GabbleHandleSet *) data;
       
   242   gabble_handle_unref (set->repo, set->type, handle);
       
   243 }
       
   244 
       
   245 /**
       
   246  * handle_set_difference_update:
       
   247  * @set: a #GabbleHandleSet to update
       
   248  * @remove: a #GIntSet of handles to remove
       
   249  *
       
   250  * Remove a set of handles from a handle set, dereferencing those which are
       
   251  * members. The GIntSet returned must be freed with g_intset_destroy.
       
   252  *
       
   253  * Returns: the handles which were removed
       
   254  */
       
   255 
       
   256 GIntSet *
       
   257 handle_set_difference_update (GabbleHandleSet *set, const GIntSet *remove)
       
   258 {
       
   259   GIntSet *ret, *tmp;
       
   260 
       
   261   g_return_val_if_fail (set != NULL, NULL);
       
   262   g_return_val_if_fail (remove != NULL, NULL);
       
   263 
       
   264   /* dereference each of REMOVE n CURRENT */
       
   265   ret = g_intset_intersection (remove, set->intset);
       
   266   g_intset_foreach (ret, unref_one, set);
       
   267 
       
   268   /* update CURRENT to be CURRENT - REMOVE */
       
   269   tmp = g_intset_difference (set->intset, remove);
       
   270   g_intset_destroy (set->intset);
       
   271   set->intset = tmp;
       
   272 
       
   273   return ret;
       
   274 }