evolution-3.6.4/e-util/e-sorter-array.c

No issues found

  1 /*
  2  * This program is free software; you can redistribute it and/or
  3  * modify it under the terms of the GNU Lesser General Public
  4  * License as published by the Free Software Foundation; either
  5  * version 2 of the License, or (at your option) version 3.
  6  *
  7  * This program is distributed in the hope that it will be useful,
  8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 10  * Lesser General Public License for more details.
 11  *
 12  * You should have received a copy of the GNU Lesser General Public
 13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 14  *
 15  *
 16  * Authors:
 17  *		Chris Lahey <clahey@ximian.com>
 18  *
 19  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 20  *
 21  */
 22 
 23 #ifdef HAVE_CONFIG_H
 24 #include <config.h>
 25 #endif
 26 
 27 #include <stdlib.h>
 28 #include <string.h>
 29 
 30 #include "e-sorter-array.h"
 31 #include "e-util.h"
 32 
 33 #define d(x)
 34 
 35 #define INCREMENT_AMOUNT 100
 36 
 37 G_DEFINE_TYPE (
 38 	ESorterArray,
 39 	e_sorter_array,
 40 	E_SORTER_TYPE)
 41 
 42 static void	esa_sort			(ESorterArray *esa);
 43 static void	esa_backsort			(ESorterArray *esa);
 44 
 45 static gint	esa_model_to_sorted		(ESorter *sorter, gint row);
 46 static gint	esa_sorted_to_model		(ESorter *sorter, gint row);
 47 static void	esa_get_model_to_sorted_array	(ESorter *sorter,
 48 						 gint **array,
 49 						 gint *count);
 50 static void	esa_get_sorted_to_model_array	(ESorter *sorter,
 51 						 gint **array,
 52 						 gint *count);
 53 static gboolean	esa_needs_sorting		(ESorter *esa);
 54 
 55 #define ESA_NEEDS_SORTING(esa) (((ESorterArray *) (esa))->compare != NULL)
 56 
 57 static gint
 58 esort_callback (gconstpointer data1,
 59                 gconstpointer data2,
 60                 gpointer user_data)
 61 {
 62 	ESorterArray *esa = user_data;
 63 	gint ret_val;
 64 	gint int1, int2;
 65 
 66 	int1 = *(gint *) data1;
 67 	int2 = *(gint *) data2;
 68 
 69 	ret_val = esa->compare (int1, int2, esa->cmp_cache, esa->closure);
 70 	if (ret_val != 0)
 71 		return ret_val;
 72 
 73 	if (int1 < int2)
 74 		return -1;
 75 	if (int1 > int2)
 76 		return 1;
 77 	return 0;
 78 }
 79 
 80 static void
 81 esa_sort (ESorterArray *esa)
 82 {
 83 	gint rows;
 84 	gint i;
 85 
 86 	if (esa->sorted)
 87 		return;
 88 
 89 	rows = esa->rows;
 90 
 91 	esa->sorted = g_new (int, rows);
 92 	for (i = 0; i < rows; i++)
 93 		esa->sorted[i] = i;
 94 
 95 	if (esa->compare) {
 96 		if (esa->create_cmp_cache)
 97 			esa->cmp_cache = esa->create_cmp_cache (esa->closure);
 98 
 99 		g_qsort_with_data (
100 			esa->sorted, rows, sizeof (gint),
101 			esort_callback, esa);
102 
103 		if (esa->cmp_cache) {
104 			g_hash_table_destroy (esa->cmp_cache);
105 			esa->cmp_cache = NULL;
106 		}
107 	}
108 }
109 
110 static void
111 esa_backsort (ESorterArray *esa)
112 {
113 	gint i, rows;
114 
115 	if (esa->backsorted)
116 		return;
117 
118 	esa_sort (esa);
119 
120 	rows = esa->rows;
121 
122 	esa->backsorted = g_new0 (int, rows);
123 
124 	for (i = 0; i < rows; i++) {
125 		esa->backsorted[esa->sorted[i]] = i;
126 	}
127 }
128 
129 static gint
130 esa_model_to_sorted (ESorter *es,
131                      gint row)
132 {
133 	ESorterArray *esa = E_SORTER_ARRAY (es);
134 
135 	g_return_val_if_fail (row >= 0, -1);
136 	g_return_val_if_fail (row < esa->rows, -1);
137 
138 	if (ESA_NEEDS_SORTING (es))
139 		esa_backsort (esa);
140 
141 	if (esa->backsorted)
142 		return esa->backsorted[row];
143 	else
144 		return row;
145 }
146 
147 static gint
148 esa_sorted_to_model (ESorter *es,
149                      gint row)
150 {
151 	ESorterArray *esa = (ESorterArray *) es;
152 
153 	g_return_val_if_fail (row >= 0, -1);
154 	g_return_val_if_fail (row < esa->rows, -1);
155 
156 	if (ESA_NEEDS_SORTING (es))
157 		esa_sort (esa);
158 
159 	if (esa->sorted)
160 		return esa->sorted[row];
161 	else
162 		return row;
163 }
164 
165 static void
166 esa_get_model_to_sorted_array (ESorter *es,
167                                gint **array,
168                                gint *count)
169 {
170 	ESorterArray *esa = E_SORTER_ARRAY (es);
171 	if (array || count) {
172 		esa_backsort (esa);
173 
174 		if (array)
175 			*array = esa->backsorted;
176 		if (count)
177 			*count = esa->rows;
178 	}
179 }
180 
181 static void
182 esa_get_sorted_to_model_array (ESorter *es,
183                                gint **array,
184                                gint *count)
185 {
186 	ESorterArray *esa = E_SORTER_ARRAY (es);
187 	if (array || count) {
188 		esa_sort (esa);
189 
190 		if (array)
191 			*array = esa->sorted;
192 		if (count)
193 			*count = esa->rows;
194 	}
195 }
196 
197 static gboolean
198 esa_needs_sorting (ESorter *es)
199 {
200 	ESorterArray *esa = E_SORTER_ARRAY (es);
201 	return esa->compare != NULL;
202 }
203 
204 void
205 e_sorter_array_clean (ESorterArray *esa)
206 {
207 	g_free (esa->sorted);
208 	esa->sorted = NULL;
209 
210 	g_free (esa->backsorted);
211 	esa->backsorted = NULL;
212 }
213 
214 void
215 e_sorter_array_set_count (ESorterArray *esa,
216                           gint count)
217 {
218 	e_sorter_array_clean (esa);
219 	esa->rows = count;
220 }
221 
222 void
223 e_sorter_array_append (ESorterArray *esa,
224                        gint count)
225 {
226 	gint i;
227 	g_free (esa->backsorted);
228 	esa->backsorted = NULL;
229 
230 	if (esa->sorted) {
231 		esa->sorted = g_renew (int, esa->sorted, esa->rows + count);
232 		for (i = 0; i < count; i++) {
233 			gint value = esa->rows;
234 			gsize pos;
235 
236 			e_bsearch (
237 				&value, esa->sorted, esa->rows,
238 				sizeof (gint), esort_callback, esa, &pos, NULL);
239 			memmove (
240 				esa->sorted + pos + 1,
241 				esa->sorted + pos,
242 				sizeof (gint) * (esa->rows - pos));
243 			esa->sorted[pos] = value;
244 			esa->rows++;
245 		}
246 	} else {
247 		esa->rows += count;
248 	}
249 }
250 
251 static void
252 esa_finalize (GObject *object)
253 {
254 	ESorterArray *esa = E_SORTER_ARRAY (object);
255 
256 	if (esa)
257 		e_sorter_array_clean (esa);
258 
259 	/* Chain up to parent's finalize() method. */
260 	G_OBJECT_CLASS (e_sorter_array_parent_class)->finalize (object);
261 }
262 
263 ESorterArray *
264 e_sorter_array_construct (ESorterArray *esa,
265                           ECreateCmpCacheFunc create_cmp_cache,
266                           ECompareRowsFunc compare,
267                           gpointer closure)
268 {
269 	esa->create_cmp_cache = create_cmp_cache;
270 	esa->compare = compare;
271 	esa->closure = closure;
272 	return esa;
273 }
274 
275 ESorterArray *
276 e_sorter_array_new (ECreateCmpCacheFunc create_cmp_cache,
277                     ECompareRowsFunc compare,
278                     gpointer closure)
279 {
280 	ESorterArray *esa = g_object_new (E_SORTER_ARRAY_TYPE, NULL);
281 
282 	return e_sorter_array_construct (esa, create_cmp_cache, compare, closure);
283 }
284 
285 static void
286 e_sorter_array_class_init (ESorterArrayClass *class)
287 {
288 	GObjectClass *object_class = G_OBJECT_CLASS (class);
289 	ESorterClass *sorter_class = E_SORTER_CLASS (class);
290 
291 	object_class->finalize = esa_finalize;
292 
293 	sorter_class->model_to_sorted           = esa_model_to_sorted;
294 	sorter_class->sorted_to_model           = esa_sorted_to_model;
295 	sorter_class->get_model_to_sorted_array = esa_get_model_to_sorted_array;
296 	sorter_class->get_sorted_to_model_array = esa_get_sorted_to_model_array;
297 	sorter_class->needs_sorting             = esa_needs_sorting;
298 }
299 
300 static void
301 e_sorter_array_init (ESorterArray *esa)
302 {
303 	esa->rows       = 0;
304 	esa->cmp_cache  = NULL;
305 	esa->create_cmp_cache = NULL;
306 	esa->compare    = NULL;
307 	esa->closure    = NULL;
308 	esa->sorted     = NULL;
309 	esa->backsorted = NULL;
310 }