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 } |
|