nautilus-3.6.3/eel/eel-glib-extensions.c

No issues found

  1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
  2 
  3 /* eel-glib-extensions.c - implementation of new functions that conceptually
  4                                 belong in glib. Perhaps some of these will be
  5                                 actually rolled into glib someday.
  6 
  7    Copyright (C) 2000 Eazel, Inc.
  8 
  9    The Gnome Library is free software; you can redistribute it and/or
 10    modify it under the terms of the GNU Library General Public License as
 11    published by the Free Software Foundation; either version 2 of the
 12    License, or (at your option) any later version.
 13 
 14    The Gnome Library is distributed in the hope that it will be useful,
 15    but WITHOUT ANY WARRANTY; without even the implied warranty of
 16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17    Library General Public License for more details.
 18 
 19    You should have received a copy of the GNU Library General Public
 20    License along with the Gnome Library; see the file COPYING.LIB.  If not,
 21    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 22    Boston, MA 02111-1307, USA.
 23 
 24    Authors: John Sullivan <sullivan@eazel.com>
 25 */
 26 
 27 #include <config.h>
 28 #include "eel-glib-extensions.h"
 29 
 30 #include "eel-debug.h"
 31 #include "eel-lib-self-check-functions.h"
 32 #include "eel-string.h"
 33 #include <glib-object.h>
 34 #include <math.h>
 35 #include <stdlib.h>
 36 
 37 /**
 38  * eel_g_str_list_equal
 39  *
 40  * Compares two lists of C strings to see if they are equal.
 41  * @list_a: First list.
 42  * @list_b: Second list.
 43  *
 44  * Return value: TRUE if the lists contain the same strings.
 45  **/
 46 gboolean
 47 eel_g_str_list_equal (GList *list_a, GList *list_b)
 48 {
 49 	GList *p, *q;
 50 
 51 	for (p = list_a, q = list_b; p != NULL && q != NULL; p = p->next, q = q->next) {
 52 		if (g_strcmp0 (p->data, q->data) != 0) {
 53 			return FALSE;
 54 		}
 55 	}
 56 	return p == NULL && q == NULL;
 57 }
 58 
 59 /**
 60  * eel_g_str_list_copy
 61  *
 62  * @list: List of strings and/or NULLs to copy.
 63  * Return value: Deep copy of @list.
 64  **/
 65 GList *
 66 eel_g_str_list_copy (GList *list)
 67 {
 68 	GList *node, *result;
 69 
 70 	result = NULL;
 71 	
 72 	for (node = g_list_last (list); node != NULL; node = node->prev) {
 73 		result = g_list_prepend (result, g_strdup (node->data));
 74 	}
 75 	return result;
 76 }
 77 
 78 gboolean
 79 eel_g_strv_equal (char **a, char **b)
 80 {
 81 	int i;
 82 
 83 	if (g_strv_length (a) != g_strv_length (b)) {
 84 		return FALSE;
 85 	}
 86 
 87 	for (i = 0; a[i] != NULL; i++) {
 88 		if (strcmp (a[i], b[i]) != 0) {
 89 			return FALSE;
 90 		}
 91 	}
 92 	return TRUE;
 93 }
 94 
 95 static int
 96 compare_pointers (gconstpointer pointer_1, gconstpointer pointer_2)
 97 {
 98 	if ((const char *) pointer_1 < (const char *) pointer_2) {
 99 		return -1;
100 	}
101 	if ((const char *) pointer_1 > (const char *) pointer_2) {
102 		return +1;
103 	}
104 	return 0;
105 }
106 
107 gboolean
108 eel_g_lists_sort_and_check_for_intersection (GList **list_1,
109 					     GList **list_2) 
110 
111 {
112 	GList *node_1, *node_2;
113 	int compare_result;
114 	
115 	*list_1 = g_list_sort (*list_1, compare_pointers);
116 	*list_2 = g_list_sort (*list_2, compare_pointers);
117 
118 	node_1 = *list_1;
119 	node_2 = *list_2;
120 
121 	while (node_1 != NULL && node_2 != NULL) {
122 		compare_result = compare_pointers (node_1->data, node_2->data);
123 		if (compare_result == 0) {
124 			return TRUE;
125 		}
126 		if (compare_result <= 0) {
127 			node_1 = node_1->next;
128 		}
129 		if (compare_result >= 0) {
130 			node_2 = node_2->next;
131 		}
132 	}
133 
134 	return FALSE;
135 }
136 
137 
138 /**
139  * eel_g_list_partition
140  * 
141  * Parition a list into two parts depending on whether the data
142  * elements satisfy a provided predicate. Order is preserved in both
143  * of the resulting lists, and the original list is consumed. A list
144  * of the items that satisfy the predicate is returned, and the list
145  * of items not satisfying the predicate is returned via the failed
146  * out argument.
147  * 
148  * @list: List to partition.
149  * @predicate: Function to call on each element.
150  * @user_data: Data to pass to function.  
151  * @failed: The GList * variable pointed to by this argument will be
152  * set to the list of elements for which the predicate returned
153  * false. */
154 
155 GList *
156 eel_g_list_partition (GList *list,
157 			   EelPredicateFunction  predicate,
158 			   gpointer user_data,
159 			   GList **failed)
160 {
161 	GList *predicate_true;
162 	GList *predicate_false;
163 	GList *reverse;
164 	GList *p;
165 	GList *next;
166 
167 	predicate_true = NULL;
168 	predicate_false = NULL;
169 
170 	reverse = g_list_reverse (list);
171 
172 	for (p = reverse; p != NULL; p = next) {
173 		next = p->next;
174 		
175 		if (next != NULL) {
176 			next->prev = NULL;
177 		}
178 
179 		if (predicate (p->data, user_data)) {
180 			p->next = predicate_true;
181  			if (predicate_true != NULL) {
182 				predicate_true->prev = p;
183 			}
184 			predicate_true = p;
185 		} else {
186 			p->next = predicate_false;
187  			if (predicate_false != NULL) {
188 				predicate_false->prev = p;
189 			}
190 			predicate_false = p;
191 		}
192 	}
193 
194 	*failed = predicate_false;
195 	return predicate_true;
196 }
197 
198 typedef struct {
199 	GList *keys;
200 	GList *values;
201 } FlattenedHashTable;
202 
203 static void
204 flatten_hash_table_element (gpointer key, gpointer value, gpointer callback_data)
205 {
206 	FlattenedHashTable *flattened_table;
207 
208 	flattened_table = callback_data;
209 	flattened_table->keys = g_list_prepend
210 		(flattened_table->keys, key);
211 	flattened_table->values = g_list_prepend
212 		(flattened_table->values, value);
213 }
214 
215 void
216 eel_g_hash_table_safe_for_each (GHashTable *hash_table,
217 				GHFunc callback,
218 				gpointer callback_data)
219 {
220 	FlattenedHashTable flattened;
221 	GList *p, *q;
222 
223 	flattened.keys = NULL;
224 	flattened.values = NULL;
225 
226 	g_hash_table_foreach (hash_table,
227 			      flatten_hash_table_element,
228 			      &flattened);
229 
230 	for (p = flattened.keys, q = flattened.values;
231 	     p != NULL;
232 	     p = p->next, q = q->next) {
233 		(* callback) (p->data, q->data, callback_data);
234 	}
235 
236 	g_list_free (flattened.keys);
237 	g_list_free (flattened.values);
238 }
239 
240 /**
241  * eel_g_object_list_copy
242  *
243  * Copy the list of objects, ref'ing each one.
244  * @list: GList of objects.
245  **/
246 GList *
247 eel_g_object_list_copy (GList *list)
248 {
249 	g_list_foreach (list, (GFunc) g_object_ref, NULL);
250 	return g_list_copy (list);
251 }
252 
253 #if !defined (EEL_OMIT_SELF_CHECK)
254 
255 static gboolean
256 eel_test_predicate (gpointer data,
257 		    gpointer callback_data)
258 {
259 	return g_ascii_strcasecmp (data, callback_data) <= 0;
260 }
261 
262 void
263 eel_self_check_glib_extensions (void)
264 {
265 	GList *compare_list_1;
266 	GList *compare_list_2;
267 	GList *compare_list_3;
268 	GList *compare_list_4;
269 	GList *compare_list_5;
270 	GList *list_to_partition;
271 	GList *expected_passed;
272 	GList *expected_failed;
273 	GList *actual_passed;
274 	GList *actual_failed;
275 	
276 	/* eel_g_str_list_equal */
277 
278 	/* We g_strdup because identical string constants can be shared. */
279 
280 	compare_list_1 = NULL;
281 	compare_list_1 = g_list_append (compare_list_1, g_strdup ("Apple"));
282 	compare_list_1 = g_list_append (compare_list_1, g_strdup ("zebra"));
283 	compare_list_1 = g_list_append (compare_list_1, g_strdup ("!@#!@$#@$!"));
284 
285 	compare_list_2 = NULL;
286 	compare_list_2 = g_list_append (compare_list_2, g_strdup ("Apple"));
287 	compare_list_2 = g_list_append (compare_list_2, g_strdup ("zebra"));
288 	compare_list_2 = g_list_append (compare_list_2, g_strdup ("!@#!@$#@$!"));
289 
290 	compare_list_3 = NULL;
291 	compare_list_3 = g_list_append (compare_list_3, g_strdup ("Apple"));
292 	compare_list_3 = g_list_append (compare_list_3, g_strdup ("zebra"));
293 
294 	compare_list_4 = NULL;
295 	compare_list_4 = g_list_append (compare_list_4, g_strdup ("Apple"));
296 	compare_list_4 = g_list_append (compare_list_4, g_strdup ("zebra"));
297 	compare_list_4 = g_list_append (compare_list_4, g_strdup ("!@#!@$#@$!"));
298 	compare_list_4 = g_list_append (compare_list_4, g_strdup ("foobar"));
299 
300 	compare_list_5 = NULL;
301 	compare_list_5 = g_list_append (compare_list_5, g_strdup ("Apple"));
302 	compare_list_5 = g_list_append (compare_list_5, g_strdup ("zzzzzebraaaaaa"));
303 	compare_list_5 = g_list_append (compare_list_5, g_strdup ("!@#!@$#@$!"));
304 
305 	EEL_CHECK_BOOLEAN_RESULT (eel_g_str_list_equal (compare_list_1, compare_list_2), TRUE);
306 	EEL_CHECK_BOOLEAN_RESULT (eel_g_str_list_equal (compare_list_1, compare_list_3), FALSE);
307 	EEL_CHECK_BOOLEAN_RESULT (eel_g_str_list_equal (compare_list_1, compare_list_4), FALSE);
308 	EEL_CHECK_BOOLEAN_RESULT (eel_g_str_list_equal (compare_list_1, compare_list_5), FALSE);
309 
310 	g_list_free_full (compare_list_1, g_free);
311 	g_list_free_full (compare_list_2, g_free);
312 	g_list_free_full (compare_list_3, g_free);
313 	g_list_free_full (compare_list_4, g_free);
314 	g_list_free_full (compare_list_5, g_free);
315 
316 	/* eel_g_list_partition */
317 
318 	list_to_partition = NULL;
319 	list_to_partition = g_list_append (list_to_partition, "Cadillac");
320 	list_to_partition = g_list_append (list_to_partition, "Pontiac");
321 	list_to_partition = g_list_append (list_to_partition, "Ford");
322 	list_to_partition = g_list_append (list_to_partition, "Range Rover");
323 	
324 	expected_passed = NULL;
325 	expected_passed = g_list_append (expected_passed, "Cadillac");
326 	expected_passed = g_list_append (expected_passed, "Ford");
327 	
328 	expected_failed = NULL;
329 	expected_failed = g_list_append (expected_failed, "Pontiac");
330 	expected_failed = g_list_append (expected_failed, "Range Rover");
331 	
332 	actual_passed = eel_g_list_partition (list_to_partition, 
333 						   eel_test_predicate,
334 						   "m",
335 						   &actual_failed);
336 	
337 	EEL_CHECK_BOOLEAN_RESULT (eel_g_str_list_equal (expected_passed, actual_passed), TRUE);
338 	EEL_CHECK_BOOLEAN_RESULT (eel_g_str_list_equal (expected_failed, actual_failed), TRUE);
339 	
340 	/* Don't free "list_to_partition", since it is consumed
341 	 * by eel_g_list_partition.
342 	 */
343 	
344 	g_list_free (expected_passed);
345 	g_list_free (actual_passed);
346 	g_list_free (expected_failed);
347 	g_list_free (actual_failed);
348 }
349 
350 #endif /* !EEL_OMIT_SELF_CHECK */