1 /*
2 * go-data.c :
3 *
4 * Copyright (C) 2003-2005 Jody Goldberg (jody@gnome.org)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) version 3.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19 * USA
20 */
21
22 #include <goffice/goffice-config.h>
23 #include "go-data.h"
24 #include "go-data-impl.h"
25 #include <goffice/math/go-math.h>
26 #include <goffice/math/go-rangefunc.h>
27
28 #include <gsf/gsf-impl-utils.h>
29 #include <glib/gi18n-lib.h>
30 #include <string.h>
31
32 /**
33 * GODataFlags:
34 * @GO_DATA_CACHE_IS_VALID: data in cache are valid.
35 * @GO_DATA_IS_EDITABLE: data can be edited.
36 * @GO_DATA_SIZE_CACHED: cached size is valid.
37 * @GO_DATA_HAS_VALUE: object is not empty.
38 **/
39
40 /**
41 * GODataClass:
42 * @base: base class.
43 * @dup: duplicates the #GOData.
44 * @eq: tests if the data are equal.
45 * @preferred_fmt: gets the preferred format.
46 * @date_conv: gets the #GODateConventions.
47 * @serialize: serializes.
48 * @unserialize: unserializes.
49 * @emit_changed: signals the data have changed.
50 * @get_n_dimensions: gets the dimensions number.
51 * @get_sizes: gets the sizes.
52 * @get_values: gets the values.
53 * @get_bounds: gets the bounds.
54 * @get_value: gets a value.
55 * @get_string: gets a string.
56 * @get_markup: gets the #PangoAttrList* for the string.
57 * @is_valid: checks if the data are valid.
58 **/
59
60 /**
61 * GODataScalarClass:
62 * @base: base class.
63 * @get_value: gets the value.
64 * @get_str: gets the string.
65 * @get_markup: gets the #PangoAttrList* for the string.
66 **/
67
68 /**
69 * GODataVectorClass:
70 * @base: base class.
71 * @load_len: loads the vector length.
72 * @load_values: loads the values in the cache.
73 * @get_value: gets a value.
74 * @get_str: gets a string.
75 * @get_markup: gets the #PangoAttrList* for the string.
76 **/
77
78 /**
79 * GODataMatrixClass:
80 * @base: base class.
81 * @load_size: loads the matrix length.
82 * @load_values: loads the values in the cache.
83 * @get_value: gets a value.
84 * @get_str: gets a string.
85 * @get_markup: gets the #PangoAttrList* for the string.
86 **/
87
88 #define GO_DATA_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GO_TYPE_DATA, GODataClass))
89 #define GO_IS_DATA_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GO_TYPE_DATA))
90 #define GO_DATA_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GO_TYPE_DATA, GODataClass))
91
92 /**
93 * GODataMatrixSize:
94 * @rows: rows number, negative if dirty, includes missing values.
95 * @columns: columns number, negative if dirty, includes missing values.
96 **/
97
98 enum {
99 CHANGED,
100 LAST_SIGNAL
101 };
102
103 static gulong go_data_signals [LAST_SIGNAL] = { 0, };
104
105 /* trivial fall back */
106 static GOData *
go_data_dup_real(GOData const * src)107 go_data_dup_real (GOData const *src)
108 {
109 gpointer user = NULL; /* FIXME? */
110 char *str = go_data_serialize (src, user);
111 GOData *dst = g_object_new (G_OBJECT_TYPE (src), NULL);
112 if (dst != NULL)
113 go_data_unserialize (dst, str, user);
114 g_free (str);
115
116 return dst;
117 }
118
119 static void
go_data_init(GOData * data)120 go_data_init (GOData *data)
121 {
122 data->flags = 0;
123 }
124
125 #if 0
126 static GObjectClass *parent_klass;
127 static void
128 go_data_finalize (GOData *obj)
129 {
130 g_warning ("finalize");
131 (parent_klass->finalize) (obj);
132 }
133 #endif
134
135 static void
go_data_class_init(GODataClass * klass)136 go_data_class_init (GODataClass *klass)
137 {
138 go_data_signals [CHANGED] = g_signal_new ("changed",
139 G_TYPE_FROM_CLASS (klass),
140 G_SIGNAL_RUN_LAST,
141 G_STRUCT_OFFSET (GODataClass, changed),
142 NULL, NULL,
143 g_cclosure_marshal_VOID__VOID,
144 G_TYPE_NONE, 0);
145 klass->dup = go_data_dup_real;
146 #if 0
147 {
148 GObjectClass *gobj_klass = (GObjectClass *)klass;
149 gobj_klass->finalize = go_data_finalize;
150 parent_klass = g_type_class_peek_parent (klass);
151 }
152 #endif
153 }
154
GSF_CLASS_ABSTRACT(GOData,go_data,go_data_class_init,go_data_init,G_TYPE_OBJECT)155 GSF_CLASS_ABSTRACT (GOData, go_data,
156 go_data_class_init, go_data_init,
157 G_TYPE_OBJECT)
158
159 /**
160 * go_data_dup:
161 * @src: #GOData
162 *
163 * Returns: (transfer full): A deep copy of @src.
164 **/
165 GOData *
166 go_data_dup (GOData const *src)
167 {
168 if (src != NULL) {
169 GODataClass const *klass = GO_DATA_GET_CLASS (src);
170 g_return_val_if_fail (klass != NULL, NULL);
171 return (*klass->dup) (src);
172 }
173 return NULL;
174 }
175
176 /**
177 * go_data_eq :
178 * @a: #GOData
179 * @b: #GOData
180 *
181 * Returns: TRUE if @a and @b are the same
182 **/
183 gboolean
go_data_eq(GOData const * a,GOData const * b)184 go_data_eq (GOData const *a, GOData const *b)
185 {
186 if (a == b)
187 return TRUE;
188 else {
189 GODataClass *a_klass = GO_DATA_GET_CLASS (a);
190 GODataClass *b_klass = GO_DATA_GET_CLASS (b);
191
192 g_return_val_if_fail (a_klass != NULL, FALSE);
193 g_return_val_if_fail (a_klass->eq != NULL, FALSE);
194
195 if (a_klass != b_klass)
196 return FALSE;
197
198 return (*a_klass->eq) (a, b);
199 }
200 }
201
202 /**
203 * go_data_preferred_fmt :
204 * @dat: #GOData
205 *
206 * Caller is responsible for unrefing the result.
207 *
208 * Returns: the fmt preferred by the data
209 **/
210 GOFormat const *
go_data_preferred_fmt(GOData const * dat)211 go_data_preferred_fmt (GOData const *dat)
212 {
213 GODataClass const *klass = GO_DATA_GET_CLASS (dat);
214 g_return_val_if_fail (klass != NULL, NULL);
215 if (klass->preferred_fmt)
216 return klass->preferred_fmt (dat);
217 return NULL;
218 }
219
220 /**
221 * go_data_date_conv :
222 * @dat: #GOData
223 *
224 * Returns: the date conventions used by the data, or %NULL if not determined.
225 **/
226 GODateConventions const *
go_data_date_conv(GOData const * dat)227 go_data_date_conv (GOData const *dat)
228 {
229 GODataClass const *klass = GO_DATA_GET_CLASS (dat);
230 g_return_val_if_fail (klass != NULL, NULL);
231 if (klass->date_conv)
232 return klass->date_conv (dat);
233 return NULL;
234 }
235
236
237 /**
238 * go_data_serialize :
239 * @dat: #GOData
240 * @user: a gpointer describing the context.
241 *
242 * NOTE : This is the _source_ not the content. (I.e., this refers to the
243 * expression, not its current value.)
244 *
245 * Returns: a string representation of the data source that the caller is
246 * responsible for freeing
247 **/
248 char *
go_data_serialize(GOData const * dat,gpointer user)249 go_data_serialize (GOData const *dat, gpointer user)
250 {
251 GODataClass const *klass = GO_DATA_GET_CLASS (dat);
252 g_return_val_if_fail (klass != NULL, NULL);
253 return (*klass->serialize) (dat, user);
254 }
255
256 /**
257 * go_data_unserialize :
258 * @dat: #GOData
259 * @str: string to parse
260 * @user: a gpointer describing the context.
261 *
262 * De-serializes the source information returned from go_data_serialize.
263 *
264 * Returns: %FALSE on error.
265 **/
266 gboolean
go_data_unserialize(GOData * dat,char const * str,gpointer user)267 go_data_unserialize (GOData *dat, char const *str, gpointer user)
268 {
269 GODataClass const *klass = GO_DATA_GET_CLASS (dat);
270 g_return_val_if_fail (klass != NULL, FALSE);
271 /* an empty string is not valid, see #46 */
272 g_return_val_if_fail (str && *str, FALSE);
273 return (*klass->unserialize) (dat, str, user);
274 }
275
276 gboolean
go_data_is_valid(GOData const * data)277 go_data_is_valid (GOData const *data)
278 {
279 GODataClass const *klass = GO_DATA_GET_CLASS (data);
280 g_return_val_if_fail (klass != NULL, FALSE);
281 return (klass->is_valid != NULL)? (*klass->is_valid) (data): FALSE;
282 }
283
284 /**
285 * go_data_emit_changed :
286 * @dat: #GOData
287 *
288 * protected utility to emit a 'changed' signal
289 **/
290 void
go_data_emit_changed(GOData * dat)291 go_data_emit_changed (GOData *dat)
292 {
293 GODataClass const *klass = GO_DATA_GET_CLASS (dat);
294
295 g_return_if_fail (klass != NULL);
296
297 if (klass->emit_changed)
298 (*klass->emit_changed) (dat);
299
300 g_signal_emit (G_OBJECT (dat), go_data_signals [CHANGED], 0);
301 }
302
303 typedef enum {
304 GO_DATA_VARIATION_CHECK_INCREASING,
305 GO_DATA_VARIATION_CHECK_DECREASING,
306 GO_DATA_VARIATION_CHECK_UNIFORMLY
307 } GODataVariationCheck;
308
309 static gboolean
go_data_check_variation(GOData * data,GODataVariationCheck check)310 go_data_check_variation (GOData *data, GODataVariationCheck check)
311 {
312 double *values;
313 unsigned int n_values;
314
315 g_return_val_if_fail (GO_IS_DATA (data), FALSE);
316
317 values = go_data_get_values (data);
318 if (values == NULL)
319 return FALSE;
320
321 n_values = go_data_get_n_values (data);
322 if (n_values < 1)
323 return FALSE;
324
325 switch (check) {
326 case GO_DATA_VARIATION_CHECK_UNIFORMLY:
327 return go_range_vary_uniformly (values, n_values);
328 case GO_DATA_VARIATION_CHECK_INCREASING:
329 return go_range_increasing (values, n_values);
330 default:
331 return go_range_decreasing (values, n_values);
332 }
333 }
334
335 gboolean
go_data_is_increasing(GOData * data)336 go_data_is_increasing (GOData *data)
337 {
338 return go_data_check_variation (data, GO_DATA_VARIATION_CHECK_INCREASING);
339 }
340
341 gboolean
go_data_is_decreasing(GOData * data)342 go_data_is_decreasing (GOData *data)
343 {
344 return go_data_check_variation (data, GO_DATA_VARIATION_CHECK_DECREASING);
345 }
346
347 gboolean
go_data_is_varying_uniformly(GOData * data)348 go_data_is_varying_uniformly (GOData *data)
349 {
350 return go_data_check_variation (data, GO_DATA_VARIATION_CHECK_UNIFORMLY);
351 }
352
353 gboolean
go_data_has_value(GOData const * data)354 go_data_has_value (GOData const *data)
355 {
356 g_return_val_if_fail (GO_IS_DATA (data), FALSE);
357 if (!(data->flags & GO_DATA_CACHE_IS_VALID))
358 go_data_get_values (GO_DATA (data));
359 return data->flags & GO_DATA_HAS_VALUE;
360 }
361
362 unsigned int
go_data_get_n_dimensions(GOData * data)363 go_data_get_n_dimensions (GOData *data)
364 {
365 GODataClass const *data_class;
366
367 g_return_val_if_fail (GO_IS_DATA (data), 0);
368
369 data_class = GO_DATA_GET_CLASS (data);
370 g_return_val_if_fail (data_class->get_n_dimensions != NULL, 0);
371
372 return data_class->get_n_dimensions (data);
373 }
374
375 unsigned int
go_data_get_n_values(GOData * data)376 go_data_get_n_values (GOData *data)
377 {
378 GODataClass const *data_class;
379 unsigned int n_values;
380 unsigned int n_dimensions;
381 unsigned int *sizes;
382 unsigned int i;
383
384 g_return_val_if_fail (GO_IS_DATA (data), 0);
385
386 data_class = GO_DATA_GET_CLASS (data);
387 g_return_val_if_fail (data_class->get_n_dimensions != NULL, 0);
388
389 n_dimensions = data_class->get_n_dimensions (data);
390 if (n_dimensions < 1)
391 return 1;
392
393 sizes = g_newa (unsigned int, n_dimensions);
394
395 g_return_val_if_fail (data_class->get_sizes != NULL, 0);
396
397 data_class->get_sizes (data, sizes);
398
399 n_values = 1;
400 for (i = 0; i < n_dimensions; i++)
401 n_values *= sizes[i];
402
403 return n_values;
404 }
405
406 static void
go_data_get_sizes(GOData * data,unsigned int n_dimensions,unsigned int * sizes)407 go_data_get_sizes (GOData *data, unsigned int n_dimensions, unsigned int *sizes)
408 {
409 GODataClass const *data_class;
410 unsigned int actual_n_dimensions;
411
412 g_return_if_fail (n_dimensions > 0);
413 g_return_if_fail (sizes != NULL);
414
415 data_class = GO_DATA_GET_CLASS (data);
416
417 g_return_if_fail (data_class->get_n_dimensions != NULL);
418
419 actual_n_dimensions = data_class->get_n_dimensions (data);
420 if (actual_n_dimensions != n_dimensions) {
421 unsigned int i;
422
423 g_warning ("[GOData::get_sizes] Number of dimension mismatch (requested %d - actual %d)",
424 n_dimensions, actual_n_dimensions);
425
426 for (i = 0; i < n_dimensions; i++)
427 sizes[i] = 0;
428
429 return;
430 }
431
432 data_class->get_sizes (data, sizes);
433 }
434
435 unsigned int
go_data_get_vector_size(GOData * data)436 go_data_get_vector_size (GOData *data)
437 {
438 unsigned int size;
439
440 g_return_val_if_fail (GO_IS_DATA (data), 0);
441
442 go_data_get_sizes (data, 1, &size);
443
444 return size;
445 }
446
447 void
go_data_get_matrix_size(GOData * data,unsigned int * n_rows,unsigned int * n_columns)448 go_data_get_matrix_size (GOData *data, unsigned int *n_rows, unsigned int *n_columns)
449 {
450 unsigned int sizes[2];
451
452 if (!GO_IS_DATA (data)) {
453 if (n_columns != NULL)
454 *n_columns = 0;
455
456 if (n_rows != NULL)
457 *n_rows = 0;
458
459 g_return_if_fail (GO_IS_DATA (data));
460 }
461
462 go_data_get_sizes (data, 2, sizes);
463
464 if (n_columns != NULL)
465 *n_columns = sizes[0];
466
467 if (n_rows != NULL)
468 *n_rows = sizes[1];
469 }
470
471 double *
go_data_get_values(GOData * data)472 go_data_get_values (GOData *data)
473 {
474 GODataClass const *data_class;
475
476 g_return_val_if_fail (GO_IS_DATA (data), NULL);
477
478 data_class = GO_DATA_GET_CLASS (data);
479
480 g_return_val_if_fail (data_class->get_values != NULL, NULL);
481
482 return data_class->get_values (data);
483 }
484
485 void
go_data_get_bounds(GOData * data,double * minimum,double * maximum)486 go_data_get_bounds (GOData *data, double *minimum, double *maximum)
487 {
488 GODataClass const *data_class;
489 double dummy;
490
491 g_return_if_fail (GO_IS_DATA (data));
492 g_return_if_fail (minimum != NULL && maximum != NULL);
493
494 if (maximum == NULL)
495 maximum = &dummy;
496 else if (minimum == NULL)
497 minimum = &dummy;
498
499 data_class = GO_DATA_GET_CLASS (data);
500
501 g_return_if_fail (data_class->get_bounds != NULL);
502
503 data_class->get_bounds (data, minimum, maximum);
504 }
505
506 static double
go_data_get_value(GOData * data,unsigned int n_coordinates,unsigned int * coordinates)507 go_data_get_value (GOData *data, unsigned int n_coordinates, unsigned int *coordinates)
508 {
509 GODataClass const *data_class;
510 unsigned int n_dimensions;
511
512 g_return_val_if_fail (GO_IS_DATA (data), go_nan);
513
514 data_class = GO_DATA_GET_CLASS (data);
515
516 n_dimensions = data_class->get_n_dimensions (data);
517 if (n_dimensions != n_coordinates) {
518 g_warning ("[GOData::get_value] Wrong number of coordinates (given %d - needed %d)",
519 n_coordinates, n_dimensions);
520
521 return go_nan;
522 }
523
524 return data_class->get_value (data, coordinates);
525 }
526
527 double
go_data_get_scalar_value(GOData * data)528 go_data_get_scalar_value (GOData *data)
529 {
530 return go_data_get_value (data, 0, NULL);
531 }
532
533 double
go_data_get_vector_value(GOData * data,unsigned int column)534 go_data_get_vector_value (GOData *data, unsigned int column)
535 {
536 return go_data_get_value (data, 1, &column);
537 }
538
539 double
go_data_get_matrix_value(GOData * data,unsigned int row,unsigned int column)540 go_data_get_matrix_value (GOData *data, unsigned int row, unsigned int column)
541 {
542 unsigned int coordinates[2];
543
544 coordinates[0] = column;
545 coordinates[1] = row;
546
547 return go_data_get_value (data, 2, coordinates);
548 }
549
550 static char *
go_data_get_string(GOData * data,unsigned int n_coordinates,unsigned int * coordinates)551 go_data_get_string (GOData *data, unsigned int n_coordinates, unsigned int *coordinates)
552 {
553 GODataClass const *data_class;
554 unsigned int n_dimensions;
555
556 g_return_val_if_fail (GO_IS_DATA (data), NULL);
557
558 data_class = GO_DATA_GET_CLASS (data);
559
560 n_dimensions = data_class->get_n_dimensions (data);
561 if (n_dimensions != n_coordinates) {
562 g_warning ("[GOData::get_string] Wrong number of coordinates (given %d - needed %d)",
563 n_coordinates, n_dimensions);
564
565 return NULL;
566 }
567
568 return data_class->get_string (data, coordinates);
569 }
570
571 char *
go_data_get_scalar_string(GOData * data)572 go_data_get_scalar_string (GOData *data)
573 {
574 return go_data_get_string (data, 0, NULL);
575 }
576
577 char *
go_data_get_vector_string(GOData * data,unsigned int column)578 go_data_get_vector_string (GOData *data, unsigned int column)
579 {
580 return go_data_get_string (data, 1, &column);
581 }
582
583 char *
go_data_get_matrix_string(GOData * data,unsigned int row,unsigned int column)584 go_data_get_matrix_string (GOData *data, unsigned int row, unsigned int column)
585 {
586 unsigned int coordinates[2];
587
588 coordinates[0] = column;
589 coordinates[1] = row;
590
591 return go_data_get_string (data, 2, coordinates);
592 }
593
594 static PangoAttrList *
go_data_get_markup(GOData * data,unsigned int n_coordinates,unsigned int * coordinates)595 go_data_get_markup (GOData *data, unsigned int n_coordinates, unsigned int *coordinates)
596 {
597 GODataClass const *data_class;
598 unsigned int n_dimensions;
599
600 g_return_val_if_fail (GO_IS_DATA (data), NULL);
601
602 data_class = GO_DATA_GET_CLASS (data);
603
604 n_dimensions = data_class->get_n_dimensions (data);
605 if (n_dimensions != n_coordinates) {
606 g_warning ("[GOData::get_markup] Wrong number of coordinates (given %d - needed %d)",
607 n_coordinates, n_dimensions);
608
609 return NULL;
610 }
611
612 return (data_class->get_markup)? data_class->get_markup (data, coordinates): NULL;
613 }
614
615 PangoAttrList *
go_data_get_scalar_markup(GOData * data)616 go_data_get_scalar_markup (GOData *data)
617 {
618 return go_data_get_markup (data, 0, NULL);
619 }
620
621 PangoAttrList *
go_data_get_vector_markup(GOData * data,unsigned int column)622 go_data_get_vector_markup (GOData *data, unsigned int column)
623 {
624 return go_data_get_markup (data, 1, &column);
625 }
626
627 PangoAttrList *
go_data_get_matrix_markup(GOData * data,unsigned int row,unsigned int column)628 go_data_get_matrix_markup (GOData *data, unsigned int row, unsigned int column)
629 {
630 unsigned int coordinates[2];
631
632 coordinates[0] = column;
633 coordinates[1] = row;
634
635 return go_data_get_markup (data, 2, coordinates);
636 }
637
638 /*************************************************************************/
639
640 #define GO_DATA_SCALAR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GO_TYPE_DATA_SCALAR, GODataScalarClass))
641 #define GO_IS_DATA_SCALAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GO_TYPE_DATA_SCALAR))
642 #define GO_DATA_SCALAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GO_TYPE_DATA_SCALAR, GODataScalarClass))
643
644 static unsigned int
_data_scalar_get_n_dimensions(GOData * data)645 _data_scalar_get_n_dimensions (GOData *data)
646 {
647 return 0;
648 }
649
650 static double *
_data_scalar_get_values(GOData * data)651 _data_scalar_get_values (GOData *data)
652 {
653 GODataScalar *scalar = (GODataScalar *) data;
654
655 go_data_scalar_get_value (scalar);
656
657 return &scalar->value;
658 }
659
660 static void
_data_scalar_get_bounds(GOData * data,double * minimum,double * maximum)661 _data_scalar_get_bounds (GOData *data, double *minimum, double *maximum)
662 {
663 GODataScalar *scalar = (GODataScalar *) data;
664
665 go_data_scalar_get_value (scalar);
666
667 *minimum = scalar->value;
668 *maximum = scalar->value;
669 }
670
671 static double
_data_scalar_get_value(GOData * data,unsigned int * coordinates)672 _data_scalar_get_value (GOData *data, unsigned int *coordinates)
673 {
674 return go_data_scalar_get_value ((GODataScalar *) data);
675 }
676
677 static char *
_data_scalar_get_string(GOData * data,unsigned int * coordinates)678 _data_scalar_get_string (GOData *data, unsigned int *coordinates)
679 {
680 return g_strdup (go_data_scalar_get_str ((GODataScalar *) data));
681 }
682
683 static PangoAttrList *
_data_scalar_get_markup(GOData * data,unsigned int * coordinates)684 _data_scalar_get_markup (GOData *data, unsigned int *coordinates)
685 {
686 return pango_attr_list_copy ((PangoAttrList *) go_data_scalar_get_markup ((GODataScalar *) data));
687 }
688
689 static void
go_data_scalar_class_init(GODataClass * data_class)690 go_data_scalar_class_init (GODataClass *data_class)
691 {
692 data_class->get_n_dimensions = _data_scalar_get_n_dimensions;
693 data_class->get_values = _data_scalar_get_values;
694 data_class->get_bounds = _data_scalar_get_bounds;
695 data_class->get_value = _data_scalar_get_value;
696 data_class->get_string = _data_scalar_get_string;
697 data_class->get_markup = _data_scalar_get_markup;
698 }
699
GSF_CLASS_ABSTRACT(GODataScalar,go_data_scalar,go_data_scalar_class_init,NULL,GO_TYPE_DATA)700 GSF_CLASS_ABSTRACT (GODataScalar, go_data_scalar,
701 go_data_scalar_class_init, NULL,
702 GO_TYPE_DATA)
703
704 double
705 go_data_scalar_get_value (GODataScalar *scalar)
706 {
707 GODataScalarClass const *klass = GO_DATA_SCALAR_GET_CLASS (scalar);
708 g_return_val_if_fail (klass != NULL, 0.); /* TODO : make this a nan */
709 scalar->value = (*klass->get_value) (scalar);
710
711 return scalar->value;
712 }
713
714 char const *
go_data_scalar_get_str(GODataScalar * scalar)715 go_data_scalar_get_str (GODataScalar *scalar)
716 {
717 GODataScalarClass const *klass = GO_DATA_SCALAR_GET_CLASS (scalar);
718 g_return_val_if_fail (klass != NULL, "");
719 return (*klass->get_str) (scalar);
720 }
721
722 PangoAttrList const *
go_data_scalar_get_markup(GODataScalar * scalar)723 go_data_scalar_get_markup (GODataScalar *scalar)
724 {
725 GODataScalarClass const *klass = GO_DATA_SCALAR_GET_CLASS (scalar);
726 g_return_val_if_fail (klass != NULL, NULL);
727 return (klass->get_markup)? (*klass->get_markup) (scalar): NULL;
728 }
729
730 /*************************************************************************/
731
732 #define GO_DATA_VECTOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GO_TYPE_DATA_VECTOR, GODataVectorClass))
733 #define GO_IS_DATA_VECTOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GO_TYPE_DATA_VECTOR))
734 #define GO_DATA_VECTOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GO_TYPE_DATA_VECTOR, GODataVectorClass))
735
736 static void
_data_vector_emit_changed(GOData * data)737 _data_vector_emit_changed (GOData *data)
738 {
739 data->flags &= ~(GO_DATA_CACHE_IS_VALID | GO_DATA_VECTOR_LEN_CACHED | GO_DATA_HAS_VALUE);
740 }
741
742 static unsigned int
_data_vector_get_n_dimensions(GOData * data)743 _data_vector_get_n_dimensions (GOData *data)
744 {
745 return 1;
746 }
747
748 static void
_data_vector_get_sizes(GOData * data,unsigned int * sizes)749 _data_vector_get_sizes (GOData *data, unsigned int *sizes)
750 {
751 GODataVector *vector = (GODataVector *) data;
752
753 sizes[0] = go_data_vector_get_len (vector);
754 }
755
756 static double *
_data_vector_get_values(GOData * data)757 _data_vector_get_values (GOData *data)
758 {
759 return go_data_vector_get_values ((GODataVector *) data);
760 }
761
762 static void
_data_vector_get_bounds(GOData * data,double * minimum,double * maximum)763 _data_vector_get_bounds (GOData *data, double *minimum, double *maximum)
764 {
765 go_data_vector_get_minmax ((GODataVector *) data, minimum, maximum);
766 }
767
768 static double
_data_vector_get_value(GOData * data,unsigned int * coordinates)769 _data_vector_get_value (GOData *data, unsigned int *coordinates)
770 {
771 return go_data_vector_get_value ((GODataVector *) data, coordinates[0]);
772 }
773
774 static char *
_data_vector_get_string(GOData * data,unsigned int * coordinates)775 _data_vector_get_string (GOData *data, unsigned int *coordinates)
776 {
777 return go_data_vector_get_str ((GODataVector *) data, coordinates[0]);
778 }
779
780 static PangoAttrList *
_data_vector_get_markup(GOData * data,unsigned int * coordinates)781 _data_vector_get_markup (GOData *data, unsigned int *coordinates)
782 {
783 return go_data_vector_get_markup ((GODataVector *) data, coordinates[0]);
784 }
785
786 static void
go_data_vector_class_init(GODataClass * data_class)787 go_data_vector_class_init (GODataClass *data_class)
788 {
789 data_class->emit_changed = _data_vector_emit_changed;
790 data_class->get_n_dimensions = _data_vector_get_n_dimensions;
791 data_class->get_sizes = _data_vector_get_sizes;
792 data_class->get_values = _data_vector_get_values;
793 data_class->get_bounds = _data_vector_get_bounds;
794 data_class->get_value = _data_vector_get_value;
795 data_class->get_string = _data_vector_get_string;
796 data_class->get_markup = _data_vector_get_markup;
797 }
798
GSF_CLASS_ABSTRACT(GODataVector,go_data_vector,go_data_vector_class_init,NULL,GO_TYPE_DATA)799 GSF_CLASS_ABSTRACT (GODataVector, go_data_vector,
800 go_data_vector_class_init, NULL,
801 GO_TYPE_DATA)
802
803 int
804 go_data_vector_get_len (GODataVector *vec)
805 {
806 if (!vec)
807 return 0;
808 if (! (vec->base.flags & GO_DATA_VECTOR_LEN_CACHED)) {
809 GODataVectorClass const *klass = GO_DATA_VECTOR_GET_CLASS (vec);
810
811 g_return_val_if_fail (klass != NULL, 0);
812
813 (*klass->load_len) (vec);
814
815 g_return_val_if_fail (vec->base.flags & GO_DATA_VECTOR_LEN_CACHED, 0);
816 }
817
818 return vec->len;
819 }
820
821 double *
go_data_vector_get_values(GODataVector * vec)822 go_data_vector_get_values (GODataVector *vec)
823 {
824 if (! (vec->base.flags & GO_DATA_CACHE_IS_VALID)) {
825 GODataVectorClass const *klass = GO_DATA_VECTOR_GET_CLASS (vec);
826
827 g_return_val_if_fail (klass != NULL, NULL);
828
829 (*klass->load_values) (vec);
830
831 {
832 double min, max;
833 go_data_get_bounds (&vec->base, &min, &max);
834 if (go_finite (min) && go_finite (max) && min <= max)
835 vec->base.flags |= GO_DATA_HAS_VALUE;
836
837 }
838
839 g_return_val_if_fail (vec->base.flags & GO_DATA_CACHE_IS_VALID, NULL);
840 }
841
842 return vec->values;
843 }
844
845 double
go_data_vector_get_value(GODataVector * vec,unsigned i)846 go_data_vector_get_value (GODataVector *vec, unsigned i)
847 {
848 if (! (vec->base.flags & GO_DATA_CACHE_IS_VALID)) {
849 GODataVectorClass const *klass = GO_DATA_VECTOR_GET_CLASS (vec);
850 g_return_val_if_fail (klass != NULL, go_nan);
851 return (*klass->get_value) (vec, i);
852 }
853
854 g_return_val_if_fail ((int)i < vec->len, go_nan);
855 return vec->values [i];
856 }
857
858 char *
go_data_vector_get_str(GODataVector * vec,unsigned i)859 go_data_vector_get_str (GODataVector *vec, unsigned i)
860 {
861 GODataVectorClass const *klass = GO_DATA_VECTOR_GET_CLASS (vec);
862 char *res;
863
864 g_return_val_if_fail (klass != NULL, g_strdup (""));
865 if (! (vec->base.flags & GO_DATA_VECTOR_LEN_CACHED)) {
866 (*klass->load_len) (vec);
867 g_return_val_if_fail (vec->base.flags & GO_DATA_VECTOR_LEN_CACHED, g_strdup (""));
868 }
869 g_return_val_if_fail ((int)i < vec->len, g_strdup (""));
870
871 res = (*klass->get_str) (vec, i);
872 if (res == NULL)
873 return g_strdup ("");
874 return res;
875 }
876
877 PangoAttrList *
go_data_vector_get_markup(GODataVector * vec,unsigned i)878 go_data_vector_get_markup (GODataVector *vec, unsigned i)
879 {
880 GODataVectorClass const *klass = GO_DATA_VECTOR_GET_CLASS (vec);
881
882 g_return_val_if_fail (klass != NULL, NULL);
883 if (! (vec->base.flags & GO_DATA_VECTOR_LEN_CACHED)) {
884 (*klass->load_len) (vec);
885 g_return_val_if_fail (vec->base.flags & GO_DATA_VECTOR_LEN_CACHED, NULL);
886 }
887 g_return_val_if_fail ((int)i < vec->len, NULL);
888
889 return (klass->get_markup)? (*klass->get_markup) (vec, i): NULL;
890 }
891
892 void
go_data_vector_get_minmax(GODataVector * vec,double * min,double * max)893 go_data_vector_get_minmax (GODataVector *vec, double *min, double *max)
894 {
895 if (! (vec->base.flags & GO_DATA_CACHE_IS_VALID)) {
896 GODataVectorClass const *klass = GO_DATA_VECTOR_GET_CLASS (vec);
897
898 g_return_if_fail (klass != NULL);
899
900 (*klass->load_values) (vec);
901
902 g_return_if_fail (vec->base.flags & GO_DATA_CACHE_IS_VALID);
903 }
904
905 if (min != NULL)
906 *min = vec->minimum;
907 if (max != NULL)
908 *max = vec->maximum;
909 }
910
911 gboolean
go_data_vector_increasing(GODataVector * vec)912 go_data_vector_increasing (GODataVector *vec)
913 {
914 double *data = go_data_vector_get_values (vec);
915 int length = go_data_vector_get_len (vec);
916 return go_range_increasing (data, length);
917 }
918
919 gboolean
go_data_vector_decreasing(GODataVector * vec)920 go_data_vector_decreasing (GODataVector *vec)
921 {
922 double *data = go_data_vector_get_values (vec);
923 int length = go_data_vector_get_len (vec);
924 return go_range_decreasing (data, length);
925 }
926
927 gboolean
go_data_vector_vary_uniformly(GODataVector * vec)928 go_data_vector_vary_uniformly (GODataVector *vec)
929 {
930 double *data = go_data_vector_get_values (vec);
931 int length = go_data_vector_get_len (vec);
932 return go_range_vary_uniformly (data, length);
933 }
934
935 /*************************************************************************/
936
937 #define GO_DATA_MATRIX_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GO_TYPE_DATA_MATRIX, GODataMatrixClass))
938 #define GO_IS_DATA_MATRIX_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GO_TYPE_DATA_MATRIX))
939 #define GO_DATA_MATRIX_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GO_TYPE_DATA_MATRIX, GODataMatrixClass))
940
941 static void
_data_matrix_emit_changed(GOData * data)942 _data_matrix_emit_changed (GOData *data)
943 {
944 data->flags &= ~(GO_DATA_CACHE_IS_VALID | GO_DATA_MATRIX_SIZE_CACHED | GO_DATA_HAS_VALUE);
945 }
946
947 static unsigned int
_data_matrix_get_n_dimensions(GOData * data)948 _data_matrix_get_n_dimensions (GOData *data)
949 {
950 return 2;
951 }
952
953 static void
_data_matrix_get_sizes(GOData * data,unsigned int * sizes)954 _data_matrix_get_sizes (GOData *data, unsigned int *sizes)
955 {
956 GODataMatrix *matrix = (GODataMatrix *) data;
957 GODataMatrixSize size;
958
959 size = go_data_matrix_get_size (matrix);
960
961 sizes[0] = size.columns;
962 sizes[1] = size.rows;
963 }
964
965 static double *
_data_matrix_get_values(GOData * data)966 _data_matrix_get_values (GOData *data)
967 {
968 return go_data_matrix_get_values ((GODataMatrix *) data);
969 }
970
971 static void
_data_matrix_get_bounds(GOData * data,double * minimum,double * maximum)972 _data_matrix_get_bounds (GOData *data, double *minimum, double *maximum)
973 {
974 go_data_matrix_get_minmax ((GODataMatrix *) data, minimum, maximum);
975 }
976
977 static double
_data_matrix_get_value(GOData * data,unsigned int * coordinates)978 _data_matrix_get_value (GOData *data, unsigned int *coordinates)
979 {
980 return go_data_matrix_get_value ((GODataMatrix *) data, coordinates[1], coordinates[0]);
981 }
982
983 static char *
_data_matrix_get_string(GOData * data,unsigned int * coordinates)984 _data_matrix_get_string (GOData *data, unsigned int *coordinates)
985 {
986 return go_data_matrix_get_str ((GODataMatrix *) data, coordinates[1], coordinates[0]);
987 }
988
989 static PangoAttrList *
_data_matrix_get_markup(GOData * data,unsigned int * coordinates)990 _data_matrix_get_markup (GOData *data, unsigned int *coordinates)
991 {
992 return go_data_matrix_get_markup ((GODataMatrix *) data, coordinates[1], coordinates[0]);
993 }
994
995 static void
go_data_matrix_class_init(GODataClass * data_class)996 go_data_matrix_class_init (GODataClass *data_class)
997 {
998 data_class->emit_changed = _data_matrix_emit_changed;
999 data_class->get_n_dimensions = _data_matrix_get_n_dimensions;
1000 data_class->get_sizes = _data_matrix_get_sizes;
1001 data_class->get_values = _data_matrix_get_values;
1002 data_class->get_bounds = _data_matrix_get_bounds;
1003 data_class->get_value = _data_matrix_get_value;
1004 data_class->get_string = _data_matrix_get_string;
1005 data_class->get_markup = _data_matrix_get_markup;
1006 }
1007
GSF_CLASS_ABSTRACT(GODataMatrix,go_data_matrix,go_data_matrix_class_init,NULL,GO_TYPE_DATA)1008 GSF_CLASS_ABSTRACT (GODataMatrix, go_data_matrix,
1009 go_data_matrix_class_init, NULL,
1010 GO_TYPE_DATA)
1011
1012 /**
1013 * go_data_matrix_get_size: (skip)
1014 * @mat: #GODataMatrix
1015 *
1016 * Returns: the matrix size
1017 **/
1018 GODataMatrixSize
1019 go_data_matrix_get_size (GODataMatrix *mat)
1020 {
1021 static GODataMatrixSize null_size = {0, 0};
1022 if (!mat)
1023 return null_size;
1024 if (! (mat->base.flags & GO_DATA_MATRIX_SIZE_CACHED)) {
1025 GODataMatrixClass const *klass = GO_DATA_MATRIX_GET_CLASS (mat);
1026
1027 g_return_val_if_fail (klass != NULL, null_size);
1028
1029 (*klass->load_size) (mat);
1030
1031 g_return_val_if_fail (mat->base.flags & GO_DATA_MATRIX_SIZE_CACHED, null_size);
1032 }
1033
1034 return mat->size;
1035 }
1036
1037 int
go_data_matrix_get_rows(GODataMatrix * mat)1038 go_data_matrix_get_rows (GODataMatrix *mat)
1039 {
1040 if (!mat)
1041 return 0;
1042 if (! (mat->base.flags & GO_DATA_MATRIX_SIZE_CACHED)) {
1043 GODataMatrixClass const *klass = GO_DATA_MATRIX_GET_CLASS (mat);
1044
1045 g_return_val_if_fail (klass != NULL, 0);
1046
1047 (*klass->load_size) (mat);
1048
1049 g_return_val_if_fail (mat->base.flags & GO_DATA_MATRIX_SIZE_CACHED, 0);
1050 }
1051
1052 return mat->size.rows;
1053 }
1054
1055 int
go_data_matrix_get_columns(GODataMatrix * mat)1056 go_data_matrix_get_columns (GODataMatrix *mat)
1057 {
1058 if (!mat)
1059 return 0;
1060 if (! (mat->base.flags & GO_DATA_MATRIX_SIZE_CACHED)) {
1061 GODataMatrixClass const *klass = GO_DATA_MATRIX_GET_CLASS (mat);
1062
1063 g_return_val_if_fail (klass != NULL, 0);
1064
1065 (*klass->load_size) (mat);
1066
1067 g_return_val_if_fail (mat->base.flags & GO_DATA_MATRIX_SIZE_CACHED, 0);
1068 }
1069
1070 return mat->size.columns;
1071 }
1072
1073 double *
go_data_matrix_get_values(GODataMatrix * mat)1074 go_data_matrix_get_values (GODataMatrix *mat)
1075 {
1076 if (! (mat->base.flags & GO_DATA_CACHE_IS_VALID)) {
1077 GODataMatrixClass const *klass = GO_DATA_MATRIX_GET_CLASS (mat);
1078
1079 g_return_val_if_fail (klass != NULL, NULL);
1080
1081 (*klass->load_values) (mat);
1082
1083 {
1084 double min, max;
1085 go_data_get_bounds (&mat->base, &min, &max);
1086 if (go_finite (min) && go_finite (max) && min <= max)
1087 mat->base.flags |= GO_DATA_HAS_VALUE;
1088 }
1089
1090 g_return_val_if_fail (mat->base.flags & GO_DATA_CACHE_IS_VALID, NULL);
1091 }
1092
1093 return mat->values;
1094 }
1095
1096 double
go_data_matrix_get_value(GODataMatrix * mat,unsigned i,unsigned j)1097 go_data_matrix_get_value (GODataMatrix *mat, unsigned i, unsigned j)
1098 {
1099 g_return_val_if_fail (((int)i < mat->size.rows) && ((int)j < mat->size.columns), go_nan);
1100 if (! (mat->base.flags & GO_DATA_CACHE_IS_VALID)) {
1101 GODataMatrixClass const *klass = GO_DATA_MATRIX_GET_CLASS (mat);
1102 g_return_val_if_fail (klass != NULL, go_nan);
1103 return (*klass->get_value) (mat, i, j);
1104 }
1105
1106 return mat->values[i * mat->size.columns + j];
1107 }
1108
1109 char *
go_data_matrix_get_str(GODataMatrix * mat,unsigned i,unsigned j)1110 go_data_matrix_get_str (GODataMatrix *mat, unsigned i, unsigned j)
1111 {
1112 GODataMatrixClass const *klass = GO_DATA_MATRIX_GET_CLASS (mat);
1113 char *res;
1114
1115 g_return_val_if_fail (klass != NULL, g_strdup (""));
1116 if (! (mat->base.flags & GO_DATA_MATRIX_SIZE_CACHED)) {
1117 (*klass->load_size) (mat);
1118 g_return_val_if_fail (mat->base.flags & GO_DATA_MATRIX_SIZE_CACHED, g_strdup (""));
1119 }
1120 g_return_val_if_fail (((int)i < mat->size.rows) && ((int)j < mat->size.columns), g_strdup (""));
1121
1122 res = (*klass->get_str) (mat, i, j);
1123 if (res == NULL)
1124 return g_strdup ("");
1125 return res;
1126 }
1127
1128 PangoAttrList *
go_data_matrix_get_markup(GODataMatrix * mat,unsigned i,unsigned j)1129 go_data_matrix_get_markup (GODataMatrix *mat, unsigned i, unsigned j)
1130 {
1131 GODataMatrixClass const *klass = GO_DATA_MATRIX_GET_CLASS (mat);
1132
1133 g_return_val_if_fail (klass != NULL, NULL);
1134 if (! (mat->base.flags & GO_DATA_MATRIX_SIZE_CACHED)) {
1135 (*klass->load_size) (mat);
1136 g_return_val_if_fail (mat->base.flags & GO_DATA_MATRIX_SIZE_CACHED, NULL);
1137 }
1138 g_return_val_if_fail (((int)i < mat->size.rows) && ((int)j < mat->size.columns), NULL);
1139
1140 return (klass->get_markup)? (*klass->get_markup) (mat, i, j): NULL;
1141 }
1142
1143 void
go_data_matrix_get_minmax(GODataMatrix * mat,double * min,double * max)1144 go_data_matrix_get_minmax (GODataMatrix *mat, double *min, double *max)
1145 {
1146 if (! (mat->base.flags & GO_DATA_CACHE_IS_VALID)) {
1147 GODataMatrixClass const *klass = GO_DATA_MATRIX_GET_CLASS (mat);
1148
1149 g_return_if_fail (klass != NULL);
1150
1151 (*klass->load_values) (mat);
1152
1153 g_return_if_fail (mat->base.flags & GO_DATA_CACHE_IS_VALID);
1154 }
1155
1156 if (min != NULL)
1157 *min = mat->minimum;
1158 if (max != NULL)
1159 *max = mat->maximum;
1160 }
1161