evolution-3.6.4/widgets/table/e-table-memory-store.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found e-table-memory-store.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
clang-analyzer no-output-found e-table-memory-store.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
  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 <string.h>
 28 
 29 #include "e-util/e-util.h"
 30 
 31 #include "e-table-memory-store.h"
 32 
 33 #define E_TABLE_MEMORY_STORE_GET_PRIVATE(obj) \
 34 	(G_TYPE_INSTANCE_GET_PRIVATE \
 35 	((obj), E_TYPE_TABLE_MEMORY_STORE, ETableMemoryStorePrivate))
 36 
 37 #define STORE_LOCATOR(etms, col, row) (*((etms)->priv->store + (row) * (etms)->priv->col_count + (col)))
 38 
 39 struct _ETableMemoryStorePrivate {
 40 	gint col_count;
 41 	ETableMemoryStoreColumnInfo *columns;
 42 	gpointer *store;
 43 };
 44 
 45 G_DEFINE_TYPE (ETableMemoryStore, e_table_memory_store, E_TYPE_TABLE_MEMORY)
 46 
 47 static gpointer
 48 duplicate_value (ETableMemoryStore *etms,
 49                  gint col,
 50                  gconstpointer val)
 51 {
 52 	switch (etms->priv->columns[col].type) {
 53 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING:
 54 		return g_strdup (val);
 55 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_PIXBUF:
 56 		if (val)
 57 			g_object_ref ((gpointer) val);
 58 		return (gpointer) val;
 59 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_OBJECT:
 60 		if (val)
 61 			g_object_ref ((gpointer) val);
 62 		return (gpointer) val;
 63 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM:
 64 		if (etms->priv->columns[col].custom.duplicate_value)
 65 			return etms->priv->columns[col].custom.duplicate_value (E_TABLE_MODEL (etms), col, val, NULL);
 66 		break;
 67 	default:
 68 		break;
 69 	}
 70 	return (gpointer) val;
 71 }
 72 
 73 static void
 74 free_value (ETableMemoryStore *etms,
 75             gint col,
 76             gpointer value)
 77 {
 78 	switch (etms->priv->columns[col].type) {
 79 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING:
 80 		g_free (value);
 81 		break;
 82 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_PIXBUF:
 83 		if (value)
 84 			g_object_unref (value);
 85 		break;
 86 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_OBJECT:
 87 		if (value)
 88 			g_object_unref (value);
 89 		break;
 90 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM:
 91 		if (etms->priv->columns[col].custom.free_value)
 92 			etms->priv->columns[col].custom.free_value (E_TABLE_MODEL (etms), col, value, NULL);
 93 		break;
 94 	default:
 95 		break;
 96 	}
 97 }
 98 
 99 static gint
100 etms_column_count (ETableModel *etm)
101 {
102 	ETableMemoryStore *etms = E_TABLE_MEMORY_STORE (etm);
103 
104 	return etms->priv->col_count;
105 }
106 
107 static gpointer
108 etms_value_at (ETableModel *etm,
109                gint col,
110                gint row)
111 {
112 	ETableMemoryStore *etms = E_TABLE_MEMORY_STORE (etm);
113 
114 	return STORE_LOCATOR (etms, col, row);
115 }
116 
117 static void
118 etms_set_value_at (ETableModel *etm,
119                    gint col,
120                    gint row,
121                    gconstpointer val)
122 {
123 	ETableMemoryStore *etms = E_TABLE_MEMORY_STORE (etm);
124 
125 	e_table_model_pre_change (etm);
126 
127 	STORE_LOCATOR (etms, col, row) = duplicate_value (etms, col, val);
128 
129 	e_table_model_cell_changed (etm, col, row);
130 }
131 
132 static gboolean
133 etms_is_cell_editable (ETableModel *etm,
134                        gint col,
135                        gint row)
136 {
137 	ETableMemoryStore *etms = E_TABLE_MEMORY_STORE (etm);
138 
139 	return etms->priv->columns[col].editable;
140 }
141 
142 /* The default for etms_duplicate_value is to return the raw value. */
143 static gpointer
144 etms_duplicate_value (ETableModel *etm,
145                       gint col,
146                       gconstpointer value)
147 {
148 	ETableMemoryStore *etms = E_TABLE_MEMORY_STORE (etm);
149 
150 	return duplicate_value (etms, col, value);
151 }
152 
153 static void
154 etms_free_value (ETableModel *etm,
155                  gint col,
156                  gpointer value)
157 {
158 	ETableMemoryStore *etms = E_TABLE_MEMORY_STORE (etm);
159 
160 	free_value (etms, col, value);
161 }
162 
163 static gpointer
164 etms_initialize_value (ETableModel *etm,
165                        gint col)
166 {
167 	ETableMemoryStore *etms = E_TABLE_MEMORY_STORE (etm);
168 
169 	switch (etms->priv->columns[col].type) {
170 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING:
171 		return g_strdup ("");
172 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_PIXBUF:
173 		return NULL;
174 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM:
175 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_OBJECT:
176 		if (etms->priv->columns[col].custom.initialize_value)
177 			return etms->priv->columns[col].custom.initialize_value (E_TABLE_MODEL (etms), col, NULL);
178 		break;
179 	default:
180 		break;
181 	}
182 	return NULL;
183 }
184 
185 static gboolean
186 etms_value_is_empty (ETableModel *etm,
187                      gint col,
188                      gconstpointer value)
189 {
190 	ETableMemoryStore *etms = E_TABLE_MEMORY_STORE (etm);
191 
192 	switch (etms->priv->columns[col].type) {
193 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING:
194 		return !(value && *(gchar *) value);
195 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_PIXBUF:
196 		return value == NULL;
197 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM:
198 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_OBJECT:
199 		if (etms->priv->columns[col].custom.value_is_empty)
200 			return etms->priv->columns[col].custom.value_is_empty (E_TABLE_MODEL (etms), col, value, NULL);
201 		break;
202 	default:
203 		break;
204 	}
205 	return value == NULL;
206 }
207 
208 static gchar *
209 etms_value_to_string (ETableModel *etm,
210                       gint col,
211                       gconstpointer value)
212 {
213 	ETableMemoryStore *etms = E_TABLE_MEMORY_STORE (etm);
214 
215 	switch (etms->priv->columns[col].type) {
216 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING:
217 		return g_strdup (value);
218 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_PIXBUF:
219 		return g_strdup ("");
220 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM:
221 	case E_TABLE_MEMORY_STORE_COLUMN_TYPE_OBJECT:
222 		if (etms->priv->columns[col].custom.value_is_empty)
223 			return etms->priv->columns[col].custom.value_to_string (E_TABLE_MODEL (etms), col, value, NULL);
224 		break;
225 	default:
226 		break;
227 	}
228 	return g_strdup_printf ("%d", GPOINTER_TO_INT (value));
229 }
230 
231 static void
232 etms_append_row (ETableModel *etm,
233                  ETableModel *source,
234                  gint row)
235 {
236 	ETableMemoryStore *etms = E_TABLE_MEMORY_STORE (etm);
237 	gpointer *new_data;
238 	gint i;
239 	gint row_count;
240 
241 	new_data = g_new (gpointer , etms->priv->col_count);
242 
243 	for (i = 0; i < etms->priv->col_count; i++) {
244 		new_data[i] = e_table_model_value_at (source, i, row);
245 	}
246 
247 	row_count = e_table_model_row_count (E_TABLE_MODEL (etms));
248 
249 	e_table_memory_store_insert_array (etms, row_count, new_data, NULL);
250 }
251 
252 static void
253 etms_finalize (GObject *object)
254 {
255 	ETableMemoryStorePrivate *priv;
256 
257 	priv = E_TABLE_MEMORY_STORE_GET_PRIVATE (object);
258 
259 	e_table_memory_store_clear (E_TABLE_MEMORY_STORE (object));
260 
261 	g_free (priv->columns);
262 	g_free (priv->store);
263 
264 	/* Chain up to parent's finalize() method. */
265 	G_OBJECT_CLASS (e_table_memory_store_parent_class)->finalize (object);
266 }
267 
268 static void
269 e_table_memory_store_init (ETableMemoryStore *etms)
270 {
271 	etms->priv = E_TABLE_MEMORY_STORE_GET_PRIVATE (etms);
272 }
273 
274 static void
275 e_table_memory_store_class_init (ETableMemoryStoreClass *class)
276 {
277 	GObjectClass *object_class;
278 	ETableModelClass *model_class;
279 
280 	g_type_class_add_private (class, sizeof (ETableMemoryStorePrivate));
281 
282 	object_class = G_OBJECT_CLASS (class);
283 	object_class->finalize = etms_finalize;
284 
285 	model_class = E_TABLE_MODEL_CLASS (class);
286 	model_class->column_count = etms_column_count;
287 	model_class->value_at = etms_value_at;
288 	model_class->set_value_at = etms_set_value_at;
289 	model_class->is_cell_editable = etms_is_cell_editable;
290 	model_class->duplicate_value = etms_duplicate_value;
291 	model_class->free_value = etms_free_value;
292 	model_class->initialize_value = etms_initialize_value;
293 	model_class->value_is_empty = etms_value_is_empty;
294 	model_class->value_to_string = etms_value_to_string;
295 	model_class->append_row = etms_append_row;
296 }
297 
298 /**
299  * e_table_memory_store_new:
300  * @col_count:
301  * @value_at:
302  * @set_value_at:
303  * @is_cell_editable:
304  * @duplicate_value:
305  * @free_value:
306  * @initialize_value:
307  * @value_is_empty:
308  * @value_to_string:
309  * @data: closure pointer.
310  *
311  * This initializes a new ETableMemoryStoreModel object.  ETableMemoryStoreModel is
312  * an implementaiton of the abstract class ETableModel.  The ETableMemoryStoreModel
313  * is designed to allow people to easily create ETableModels without having
314  * to create a new GType derived from ETableModel every time they need one.
315  *
316  * Instead, ETableMemoryStoreModel uses a setup based in callback functions, every
317  * callback function signature mimics the signature of each ETableModel method
318  * and passes the extra @data pointer to each one of the method to provide them
319  * with any context they might want to use.
320  *
321  * Returns: An ETableMemoryStoreModel object (which is also an ETableModel
322  * object).
323  */
324 ETableModel *
325 e_table_memory_store_new (ETableMemoryStoreColumnInfo *columns)
326 {
327 	ETableMemoryStore *et = g_object_new (E_TYPE_TABLE_MEMORY_STORE, NULL);
328 
329 	if (e_table_memory_store_construct (et, columns)) {
330 		return (ETableModel *) et;
331 	} else {
332 		g_object_unref (et);
333 		return NULL;
334 	}
335 }
336 
337 ETableModel *
338 e_table_memory_store_construct (ETableMemoryStore *etms,
339                                 ETableMemoryStoreColumnInfo *columns)
340 {
341 	gint i;
342 	for (i = 0; columns[i].type != E_TABLE_MEMORY_STORE_COLUMN_TYPE_TERMINATOR; i++)
343 		/* Intentionally blank */;
344 	etms->priv->col_count = i;
345 
346 	etms->priv->columns = g_new (ETableMemoryStoreColumnInfo, etms->priv->col_count + 1);
347 
348 	memcpy (etms->priv->columns, columns, (etms->priv->col_count + 1) * sizeof (ETableMemoryStoreColumnInfo));
349 
350 	return E_TABLE_MODEL (etms);
351 }
352 
353 void
354 e_table_memory_store_adopt_value_at (ETableMemoryStore *etms,
355                                      gint col,
356                                      gint row,
357                                      gpointer value)
358 {
359 	e_table_model_pre_change (E_TABLE_MODEL (etms));
360 
361 	STORE_LOCATOR (etms, col, row) = value;
362 
363 	e_table_model_cell_changed (E_TABLE_MODEL (etms), col, row);
364 }
365 
366 /* The size of these arrays is the number of columns. */
367 void
368 e_table_memory_store_insert_array (ETableMemoryStore *etms,
369                                    gint row,
370                                    gpointer *store,
371                                    gpointer data)
372 {
373 	gint row_count;
374 	gint i;
375 
376 	row_count = e_table_model_row_count (E_TABLE_MODEL (etms)) + 1;
377 	if (row == -1)
378 		row = row_count - 1;
379 	etms->priv->store = g_realloc (etms->priv->store, etms->priv->col_count * row_count * sizeof (gpointer));
380 	memmove (
381 		etms->priv->store + etms->priv->col_count * (row + 1),
382 		etms->priv->store + etms->priv->col_count * row,
383 		etms->priv->col_count * (row_count - row - 1) * sizeof (gpointer));
384 
385 	for (i = 0; i < etms->priv->col_count; i++) {
386 		STORE_LOCATOR (etms, i, row) = duplicate_value (etms, i, store[i]);
387 	}
388 
389 	e_table_memory_insert (E_TABLE_MEMORY (etms), row, data);
390 }
391 
392 void
393 e_table_memory_store_insert (ETableMemoryStore *etms,
394                              gint row,
395                              gpointer data,
396                              ...)
397 {
398 	gpointer *store;
399 	va_list args;
400 	gint i;
401 
402 	store = g_new (gpointer , etms->priv->col_count + 1);
403 
404 	va_start (args, data);
405 	for (i = 0; i < etms->priv->col_count; i++) {
406 		store[i] = va_arg (args, gpointer);
407 	}
408 	va_end (args);
409 
410 	e_table_memory_store_insert_array (etms, row, store, data);
411 
412 	g_free (store);
413 }
414 
415 void
416 e_table_memory_store_insert_adopt_array (ETableMemoryStore *etms,
417                                          gint row,
418                                          gpointer *store,
419                                          gpointer data)
420 {
421 	gint row_count;
422 	gint i;
423 
424 	row_count = e_table_model_row_count (E_TABLE_MODEL (etms)) + 1;
425 	if (row == -1)
426 		row = row_count - 1;
427 	etms->priv->store = g_realloc (etms->priv->store, etms->priv->col_count * row_count * sizeof (gpointer));
428 	memmove (
429 		etms->priv->store + etms->priv->col_count * (row + 1),
430 		etms->priv->store + etms->priv->col_count * row,
431 		etms->priv->col_count * (row_count - row - 1) * sizeof (gpointer));
432 
433 	for (i = 0; i < etms->priv->col_count; i++) {
434 		STORE_LOCATOR (etms, i, row) = store[i];
435 	}
436 
437 	e_table_memory_insert (E_TABLE_MEMORY (etms), row, data);
438 }
439 
440 void
441 e_table_memory_store_insert_adopt (ETableMemoryStore *etms,
442                                    gint row,
443                                    gpointer data,
444                                    ...)
445 {
446 	gpointer *store;
447 	va_list args;
448 	gint i;
449 
450 	store = g_new (gpointer , etms->priv->col_count + 1);
451 
452 	va_start (args, data);
453 	for (i = 0; i < etms->priv->col_count; i++) {
454 		store[i] = va_arg (args, gpointer);
455 	}
456 	va_end (args);
457 
458 	e_table_memory_store_insert_adopt_array (etms, row, store, data);
459 
460 	g_free (store);
461 }
462 
463 /**
464  * e_table_memory_store_change_array:
465  * @etms: the ETabelMemoryStore.
466  * @row:  the row we're changing.
467  * @store: an array of new values to fill the row
468  * @data: the new closure to associate with this row.
469  *
470  * frees existing values associated with a row and replaces them with
471  * duplicates of the values in store.
472  *
473  */
474 void
475 e_table_memory_store_change_array (ETableMemoryStore *etms,
476                                    gint row,
477                                    gpointer *store,
478                                    gpointer data)
479 {
480 	gint i;
481 
482 	g_return_if_fail (row >= 0 && row < e_table_model_row_count (E_TABLE_MODEL (etms)));
483 
484 	e_table_model_pre_change (E_TABLE_MODEL (etms));
485 
486 	for (i = 0; i < etms->priv->col_count; i++) {
487 		free_value (etms, i, STORE_LOCATOR (etms, i, row));
488 		STORE_LOCATOR (etms, i, row) = duplicate_value (etms, i, store[i]);
489 	}
490 
491 	e_table_memory_set_data (E_TABLE_MEMORY (etms), row, data);
492 	e_table_model_row_changed (E_TABLE_MODEL (etms), row);
493 }
494 
495 /**
496  * e_table_memory_store_change:
497  * @etms: the ETabelMemoryStore.
498  * @row:  the row we're changing.
499  * @data: the new closure to associate with this row.
500  *
501  * a varargs version of e_table_memory_store_change_array.  you must
502  * pass in etms->col_count args.
503  */
504 void
505 e_table_memory_store_change (ETableMemoryStore *etms,
506                              gint row,
507                              gpointer data,
508                              ...)
509 {
510 	gpointer *store;
511 	va_list args;
512 	gint i;
513 
514 	g_return_if_fail (row >= 0 && row < e_table_model_row_count (E_TABLE_MODEL (etms)));
515 
516 	store = g_new0 (gpointer , etms->priv->col_count + 1);
517 
518 	va_start (args, data);
519 	for (i = 0; i < etms->priv->col_count; i++) {
520 		store[i] = va_arg (args, gpointer);
521 	}
522 	va_end (args);
523 
524 	e_table_memory_store_change_array (etms, row, store, data);
525 
526 	g_free (store);
527 }
528 
529 /**
530  * e_table_memory_store_change_adopt_array:
531  * @etms: the ETableMemoryStore
532  * @row: the row we're changing.
533  * @store: an array of new values to fill the row
534  * @data: the new closure to associate with this row.
535  *
536  * frees existing values for the row and stores the values from store
537  * into it.  This function differs from
538  * e_table_memory_storage_change_adopt_array in that it does not
539  * duplicate the data.
540  */
541 void
542 e_table_memory_store_change_adopt_array (ETableMemoryStore *etms,
543                                          gint row,
544                                          gpointer *store,
545                                          gpointer data)
546 {
547 	gint i;
548 
549 	g_return_if_fail (row >= 0 && row < e_table_model_row_count (E_TABLE_MODEL (etms)));
550 
551 	for (i = 0; i < etms->priv->col_count; i++) {
552 		free_value (etms, i, STORE_LOCATOR (etms, i, row));
553 		STORE_LOCATOR (etms, i, row) = store[i];
554 	}
555 
556 	e_table_memory_set_data (E_TABLE_MEMORY (etms), row, data);
557 	e_table_model_row_changed (E_TABLE_MODEL (etms), row);
558 }
559 
560 /**
561  * e_table_memory_store_change_adopt
562  * @etms: the ETabelMemoryStore.
563  * @row:  the row we're changing.
564  * @data: the new closure to associate with this row.
565  *
566  * a varargs version of e_table_memory_store_change_adopt_array.  you
567  * must pass in etms->col_count args.
568  */
569 void
570 e_table_memory_store_change_adopt (ETableMemoryStore *etms,
571                                    gint row,
572                                    gpointer data,
573                                    ...)
574 {
575 	gpointer *store;
576 	va_list args;
577 	gint i;
578 
579 	g_return_if_fail (row >= 0 && row < e_table_model_row_count (E_TABLE_MODEL (etms)));
580 
581 	store = g_new0 (gpointer , etms->priv->col_count + 1);
582 
583 	va_start (args, data);
584 	for (i = 0; i < etms->priv->col_count; i++) {
585 		store[i] = va_arg (args, gpointer);
586 	}
587 	va_end (args);
588 
589 	e_table_memory_store_change_adopt_array (etms, row, store, data);
590 
591 	g_free (store);
592 }
593 
594 void
595 e_table_memory_store_remove (ETableMemoryStore *etms,
596                              gint row)
597 {
598 	ETableModel *model;
599 	gint column_count, row_count;
600 	gint i;
601 
602 	model = E_TABLE_MODEL (etms);
603 	column_count = e_table_model_column_count (model);
604 
605 	for (i = 0; i < column_count; i++)
606 		e_table_model_free_value (model, i, e_table_model_value_at (model, i, row));
607 
608 	row_count = e_table_model_row_count (E_TABLE_MODEL (etms)) - 1;
609 	memmove (
610 		etms->priv->store + etms->priv->col_count * row,
611 		etms->priv->store + etms->priv->col_count * (row + 1),
612 		etms->priv->col_count * (row_count - row) * sizeof (gpointer));
613 	etms->priv->store = g_realloc (etms->priv->store, etms->priv->col_count * row_count * sizeof (gpointer));
614 
615 	e_table_memory_remove (E_TABLE_MEMORY (etms), row);
616 }
617 
618 void
619 e_table_memory_store_clear (ETableMemoryStore *etms)
620 {
621 	ETableModel *model;
622 	gint row_count, column_count;
623 	gint i, j;
624 
625 	model = E_TABLE_MODEL (etms);
626 	row_count = e_table_model_row_count (model);
627 	column_count = e_table_model_column_count (model);
628 
629 	for (i = 0; i < row_count; i++) {
630 		for (j = 0; j < column_count; j++) {
631 			e_table_model_free_value (model, j, e_table_model_value_at (model, j, i));
632 		}
633 	}
634 
635 	e_table_memory_clear (E_TABLE_MEMORY (etms));
636 
637 	g_free (etms->priv->store);
638 	etms->priv->store = NULL;
639 }