No issues found
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 |
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 }