1 /*
2 * libInstPatch
3 * Copyright (C) 1999-2014 Element Green <element@elementsofsound.org>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License
7 * as published by the Free Software Foundation; version 2.1
8 * of the License only.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA or on the web at http://www.gnu.org.
19 */
20 /**
21 * SECTION: IpatchList
22 * @short_description: An object containing a list of object pointers
23 * @see_also:
24 * @stability: Stable
25 *
26 * An object which defines a list of object pointers. A #GObject reference
27 * is held to all objects until the #IpatchList itself is released.
28 */
29 #include <glib.h>
30 #include <glib-object.h>
31 #include "IpatchList.h"
32
33 static void ipatch_list_class_init(IpatchListClass *klass);
34 static void ipatch_list_finalize(GObject *gobject);
35
36 static GObjectClass *parent_class = NULL;
37
38
39 GType
ipatch_list_get_type(void)40 ipatch_list_get_type(void)
41 {
42 static GType item_type = 0;
43
44 if(!item_type)
45 {
46 static const GTypeInfo item_info =
47 {
48 sizeof(IpatchListClass), NULL, NULL,
49 (GClassInitFunc) ipatch_list_class_init, NULL, NULL,
50 sizeof(IpatchList), 0,
51 (GInstanceInitFunc) NULL,
52 };
53
54 item_type = g_type_register_static(G_TYPE_OBJECT, "IpatchList",
55 &item_info, 0);
56 }
57
58 return (item_type);
59 }
60
61 static void
ipatch_list_class_init(IpatchListClass * klass)62 ipatch_list_class_init(IpatchListClass *klass)
63 {
64 GObjectClass *obj_class = G_OBJECT_CLASS(klass);
65 parent_class = g_type_class_peek_parent(klass);
66 obj_class->finalize = ipatch_list_finalize;
67 }
68
69 static void
ipatch_list_finalize(GObject * gobject)70 ipatch_list_finalize(GObject *gobject)
71 {
72 IpatchList *list = IPATCH_LIST(gobject);
73 GList *p;
74
75 p = list->items;
76
77 while(p) /* unref all objects in list and destroy the list */
78 {
79 g_object_unref(p->data);
80 p = g_list_delete_link(p, p);
81 }
82
83 list->items = NULL;
84
85 if(parent_class->finalize)
86 {
87 parent_class->finalize(gobject);
88 }
89 }
90
91 /**
92 * ipatch_list_new:
93 *
94 * Create a new object list object. #IpatchList objects are often used to
95 * duplicate multi-thread sensitive object lists, so they can be iterated over
96 * at one's own leasure.
97 *
98 * Returns: New object list container object.
99 */
100 IpatchList *
ipatch_list_new(void)101 ipatch_list_new(void)
102 {
103 return (IPATCH_LIST(g_object_new(IPATCH_TYPE_LIST, NULL)));
104 }
105
106 /**
107 * ipatch_list_duplicate:
108 * @list: Object list to duplicate
109 *
110 * Duplicate an object list.
111 *
112 * Returns: (transfer full): New duplicate object list with a ref count of one which the
113 * caller owns.
114 */
115 IpatchList *
ipatch_list_duplicate(IpatchList * list)116 ipatch_list_duplicate(IpatchList *list)
117 {
118 IpatchList *newlist;
119 GList *p;
120
121 g_return_val_if_fail(IPATCH_IS_LIST(list), NULL);
122
123 newlist = ipatch_list_new(); /* ++ ref new list */
124 p = list->items;
125
126 while(p)
127 {
128 if(p->data)
129 {
130 g_object_ref(p->data); /* ++ ref object for new list */
131 }
132
133 newlist->items = g_list_prepend(newlist->items, p->data);
134 p = g_list_next(p);
135 }
136
137 newlist->items = g_list_reverse(newlist->items);
138
139 return (newlist); /* !! caller owns the new list reference */
140 }
141
142 /**
143 * ipatch_list_get_items:
144 * @list: List object
145 *
146 * Get the items list in a #IpatchList object. Mainly for the benefit of
147 * GObject Introspection, since it is common practice to just access the
148 * <structfield>items</structfield> field directly.
149 *
150 * Returns: (element-type GObject) (transfer none): The list of items in
151 * the @list object, which is owned by the @list and should not be
152 * modified or freed directly.
153 *
154 * Since: 1.1.0
155 */
156 GList *
ipatch_list_get_items(IpatchList * list)157 ipatch_list_get_items(IpatchList *list)
158 {
159 g_return_val_if_fail(IPATCH_IS_LIST(list), NULL);
160
161 return list->items;
162 }
163
164 /**
165 * ipatch_list_set_items:
166 * @list: List object
167 * @items: (element-type GObject) (transfer full): List of #GObject pointers to assign,
168 * @list takes over ownership, each object should be referenced already for the list
169 *
170 * Set the items list in a #IpatchList object. Mainly for the benefit of
171 * GObject Introspection, since it is common practice to just access the
172 * <structfield>items</structfield> field directly. Replaces existing items
173 * (list if any).
174 *
175 * Since: 1.1.0
176 */
177 void
ipatch_list_set_items(IpatchList * list,GList * items)178 ipatch_list_set_items(IpatchList *list, GList *items)
179 {
180 GList *p;
181
182 g_return_if_fail(IPATCH_IS_LIST(list));
183
184 for(p = list->items; p; p = g_list_delete_link(p, p))
185 {
186 g_object_unref(p->data);
187 }
188
189 list->items = items; // !! list takes over items
190 }
191
192 /**
193 * ipatch_list_append:
194 * @list: List object
195 * @object: Object to append to the list
196 *
197 * Append an object to an #IpatchList.
198 *
199 * Since: 1.1.0
200 */
201 void
ipatch_list_append(IpatchList * list,GObject * object)202 ipatch_list_append(IpatchList *list, GObject *object)
203 {
204 g_return_if_fail(IPATCH_IS_LIST(list));
205 g_return_if_fail(G_IS_OBJECT(object));
206
207 g_object_ref(object); // ++ ref for list
208 list->items = g_list_append(list->items, object);
209 }
210
211 /**
212 * ipatch_list_prepend:
213 * @list: List object
214 * @object: Object to prepend to the list
215 *
216 * Prepend an object to an #IpatchList.
217 *
218 * Since: 1.1.0
219 */
220 void
ipatch_list_prepend(IpatchList * list,GObject * object)221 ipatch_list_prepend(IpatchList *list, GObject *object)
222 {
223 g_return_if_fail(IPATCH_IS_LIST(list));
224 g_return_if_fail(G_IS_OBJECT(object));
225
226 g_object_ref(object); // ++ ref for list
227 list->items = g_list_prepend(list->items, object);
228 }
229
230 /**
231 * ipatch_list_insert:
232 * @list: List object
233 * @object: Object to insert into the list
234 * @pos: Position to insert into (0 for start of list, -1 to append)
235 *
236 * Append an object to an #IpatchList.
237 *
238 * Since: 1.1.0
239 */
240 void
ipatch_list_insert(IpatchList * list,GObject * object,int pos)241 ipatch_list_insert(IpatchList *list, GObject *object, int pos)
242 {
243 g_return_if_fail(IPATCH_IS_LIST(list));
244 g_return_if_fail(G_IS_OBJECT(object));
245
246 g_object_ref(object); // ++ ref for list
247 list->items = g_list_insert(list->items, object, pos);
248 }
249
250 /**
251 * ipatch_list_remove:
252 * @list: List object
253 * @object: Object to remove from the list
254 *
255 * Remove an object from an #IpatchList.
256 *
257 * Returns: %TRUE if found and removed, %FALSE otherwise
258 *
259 * Since: 1.1.0
260 */
261 gboolean
ipatch_list_remove(IpatchList * list,GObject * object)262 ipatch_list_remove(IpatchList *list, GObject *object)
263 {
264 GList *p;
265
266 g_return_val_if_fail(IPATCH_IS_LIST(list), FALSE);
267 g_return_val_if_fail(G_IS_OBJECT(object), FALSE);
268
269 p = g_list_find(list->items, object);
270
271 if(!p)
272 {
273 return (FALSE);
274 }
275
276 g_object_unref(p->data); // -- unref object
277 list->items = g_list_delete_link(list->items, p);
278
279 return (TRUE);
280 }
281
282 /**
283 * ipatch_list_init_iter: (skip)
284 * @list: List object
285 * @iter: Iterator to initialize
286 *
287 * Initializes a user supplied iterator (usually stack allocated) to iterate
288 * over the object @list. Further operations on @iter will use the @list.
289 */
290 void
ipatch_list_init_iter(IpatchList * list,IpatchIter * iter)291 ipatch_list_init_iter(IpatchList *list, IpatchIter *iter)
292 {
293 g_return_if_fail(IPATCH_IS_LIST(list));
294 g_return_if_fail(iter != NULL);
295
296 ipatch_iter_GList_init(iter, &list->items);
297 }
298