1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * value.c: Utilies for handling, creating, removing values.
6 * Miguel de Icaza (miguel@gnu.org).
7 * Michael Meeks (mmeeks@gnu.org)
8 * Jody Goldberg (jgolderg@home.com)
9 * Copyright (C) 2000-2009 Morten Welinder (terra@gnome.org)
12 #include <gnumeric-config.h>
13 #include <glib/gi18n-lib.h>
17 #include "parse-util.h"
19 #include "gnm-format.h"
28 #include <number-match.h>
29 #include <goffice/goffice.h>
36 #ifndef USE_VALUE_POOLS
37 #define USE_VALUE_POOLS 0
41 static GOMemChunk
*value_float_pool
;
42 static GOMemChunk
*value_error_pool
;
43 static GOMemChunk
*value_string_pool
;
44 static GOMemChunk
*value_range_pool
;
45 static GOMemChunk
*value_array_pool
;
46 #define CHUNK_ALLOC(T,p) ((T*)go_mem_chunk_alloc (p))
47 #define CHUNK_FREE(p,v) go_mem_chunk_free ((p), (v))
49 static int value_allocations
= 0;
50 #define CHUNK_ALLOC(T,c) (value_allocations++, g_slice_new (T))
51 #define CHUNK_FREE(p,v) (value_allocations--, g_slice_free1 (sizeof(*v),(v)))
57 char const *locale_name
;
58 GOString
*locale_name_str
;
59 } standard_errors
[] = {
60 { N_("#NULL!"), NULL
, NULL
},
61 { N_("#DIV/0!"), NULL
, NULL
},
62 { N_("#VALUE!"), NULL
, NULL
},
63 { N_("#REF!"), NULL
, NULL
},
64 { N_("#NAME?"), NULL
, NULL
},
65 { N_("#NUM!"), NULL
, NULL
},
66 { N_("#N/A"), NULL
, NULL
},
67 { N_("#UNKNOWN!"), NULL
, NULL
}
71 value_new_empty (void)
73 /* This is a constant. No need to allocate any memory. */
74 static const GnmValueAny v
= { VALUE_EMPTY
, NULL
};
75 return (GnmValue
*)&v
;
79 value_new_bool (gboolean b
)
81 /* These are constant. No need to allocate any memory. */
82 static const GnmValueBool vf
= { VALUE_BOOLEAN
, NULL
, FALSE
};
83 static const GnmValueBool vt
= { VALUE_BOOLEAN
, NULL
, TRUE
};
84 return (GnmValue
*) (b
? &vt
: &vf
);
90 return value_new_float (i
);
94 value_new_float (gnm_float f
)
97 GnmValueFloat
*v
= CHUNK_ALLOC (GnmValueFloat
, value_float_pool
);
98 *((GnmValueType
*)&(v
->type
)) = VALUE_FLOAT
;
101 return (GnmValue
*)v
;
103 /* FIXME: bogus ep sent here. What to do? */
104 return value_new_error_NUM (NULL
);
109 value_new_error (G_GNUC_UNUSED GnmEvalPos
const *ep
, char const *mesg
)
111 GnmValueErr
*v
= CHUNK_ALLOC (GnmValueErr
, value_error_pool
);
112 *((GnmValueType
*)&(v
->type
)) = VALUE_ERROR
;
114 v
->mesg
= go_string_new (mesg
);
115 return (GnmValue
*)v
;
119 value_new_error_str (G_GNUC_UNUSED GnmEvalPos
const *ep
, GOString
*mesg
)
121 GnmValueErr
*v
= CHUNK_ALLOC (GnmValueErr
, value_error_pool
);
122 *((GnmValueType
*)&(v
->type
)) = VALUE_ERROR
;
124 v
->mesg
= go_string_ref (mesg
);
125 return (GnmValue
*)v
;
129 value_new_error_std (GnmEvalPos
const *pos
, GnmStdError err
)
131 size_t i
= (size_t)err
;
132 g_return_val_if_fail (i
< G_N_ELEMENTS (standard_errors
), NULL
);
134 return value_new_error_str (pos
, standard_errors
[i
].locale_name_str
);
139 value_new_error_NULL (GnmEvalPos
const *pos
)
141 return value_new_error_str (pos
, standard_errors
[GNM_ERROR_NULL
].locale_name_str
);
145 value_new_error_DIV0 (GnmEvalPos
const *pos
)
147 return value_new_error_str (pos
, standard_errors
[GNM_ERROR_DIV0
].locale_name_str
);
151 value_new_error_VALUE (GnmEvalPos
const *pos
)
153 return value_new_error_str (pos
, standard_errors
[GNM_ERROR_VALUE
].locale_name_str
);
157 value_new_error_REF (GnmEvalPos
const *pos
)
159 return value_new_error_str (pos
, standard_errors
[GNM_ERROR_REF
].locale_name_str
);
163 value_new_error_NAME (GnmEvalPos
const *pos
)
165 return value_new_error_str (pos
, standard_errors
[GNM_ERROR_NAME
].locale_name_str
);
169 value_new_error_NUM (GnmEvalPos
const *pos
)
171 return value_new_error_str (pos
, standard_errors
[GNM_ERROR_NUM
].locale_name_str
);
175 value_new_error_NA (GnmEvalPos
const *pos
)
177 return value_new_error_str (pos
, standard_errors
[GNM_ERROR_NA
].locale_name_str
);
183 * @translated: If %TRUE, use localized name.
185 * Returns: (transfer none): the name of @err, possibly localized.
188 value_error_name (GnmStdError err
, gboolean translated
)
190 size_t i
= (size_t)err
;
191 g_return_val_if_fail (i
< G_N_ELEMENTS (standard_errors
), NULL
);
194 return standard_errors
[i
].locale_name
;
196 return standard_errors
[i
].C_name
;
200 * value_error_set_pos:
204 * Change the position of a ValueError.
206 * Returns: (transfer none): @err as a #GnmValue.
209 value_error_set_pos (GnmValueErr
*err
, G_GNUC_UNUSED GnmEvalPos
const *pos
)
211 g_return_val_if_fail (err
!= NULL
, NULL
);
212 g_return_val_if_fail (VALUE_IS_ERROR ((GnmValue
*)err
), NULL
);
214 /* err->src = *pos; */
215 return (GnmValue
*)err
;
219 value_error_classify (GnmValue
const *v
)
223 g_return_val_if_fail (v
!= NULL
, GNM_ERROR_UNKNOWN
);
225 if (!VALUE_IS_ERROR (v
))
226 return GNM_ERROR_UNKNOWN
;
228 for (i
= 0; i
< G_N_ELEMENTS (standard_errors
); i
++)
229 if (standard_errors
[i
].locale_name_str
== v
->v_err
.mesg
)
230 return (GnmStdError
)i
;
232 return GNM_ERROR_UNKNOWN
;
237 * value_new_string_str:
238 * @str: (transfer full): string to use for value
240 * Returns: (transfer full): a new value object.
243 value_new_string_str (GOString
*str
)
247 g_return_val_if_fail (str
!= NULL
, NULL
);
249 v
= CHUNK_ALLOC (GnmValueStr
, value_string_pool
);
250 *((GnmValueType
*)&(v
->type
)) = VALUE_STRING
;
253 return (GnmValue
*)v
;
258 * @str: string to use for value
260 * Returns: (transfer full): a new value object.
263 value_new_string (char const *str
)
265 return value_new_string_str (go_string_new (str
));
269 * value_new_string_nocopy:
270 * @str: (transfer full): string to use for value
272 * Returns: (transfer full): a new value object.
275 value_new_string_nocopy (char *str
)
277 return value_new_string_str (go_string_new_nocopy (str
));
281 value_new_cellrange_unsafe (GnmCellRef
const *a
, GnmCellRef
const *b
)
283 GnmValueRange
*v
= CHUNK_ALLOC (GnmValueRange
, value_range_pool
);
284 *((GnmValueType
*)&(v
->type
)) = VALUE_CELLRANGE
;
288 return (GnmValue
*)v
;
292 * value_new_cellrange:
294 * Create a new range reference.
296 * Attempt to do a sanity check for inverted ranges.
297 * NOTE : This is no longer necessary and will be removed.
298 * mixed mode references create the possibility of inversion.
299 * users of these values need to use the utility routines to
300 * evaluate the ranges in their context and normalize then.
303 value_new_cellrange (GnmCellRef
const *a
, GnmCellRef
const *b
,
304 int eval_col
, int eval_row
)
306 GnmValueRange
*v
= CHUNK_ALLOC (GnmValueRange
, value_range_pool
);
309 *((GnmValueType
*)&(v
->type
)) = VALUE_CELLRANGE
;
314 /* Sanity checking to avoid inverted ranges */
316 if (a
->col_relative
!= b
->col_relative
) {
317 /* Make a tmp copy of a in the same mode as b */
324 v
->cell
.a
.col
= b
->col
;
325 v
->cell
.a
.col_relative
= b
->col_relative
;
326 v
->cell
.b
.col
= a
->col
;
327 v
->cell
.b
.col_relative
= a
->col_relative
;
331 if (a
->row_relative
!= b
->row_relative
) {
332 /* Make a tmp copy of a in the same mode as b */
339 v
->cell
.a
.row
= b
->row
;
340 v
->cell
.a
.row_relative
= b
->row_relative
;
341 v
->cell
.b
.row
= a
->row
;
342 v
->cell
.b
.row_relative
= a
->row_relative
;
345 return (GnmValue
*)v
;
349 value_new_cellrange_r (Sheet
*sheet
, GnmRange
const *r
)
351 GnmValueRange
*v
= CHUNK_ALLOC (GnmValueRange
, value_range_pool
);
354 *((GnmValueType
*)&(v
->type
)) = VALUE_CELLRANGE
;
361 a
->col
= r
->start
.col
;
362 a
->row
= r
->start
.row
;
365 a
->col_relative
= b
->col_relative
= FALSE
;
366 a
->row_relative
= b
->row_relative
= FALSE
;
368 return (GnmValue
*)v
;
372 * value_new_cellrange_str:
373 * @sheet: the sheet where the cell range is evaluated. This really only needed if
374 * the range given does not include a sheet specification.
375 * @str: a range specification (ex: "A1", "A1:C3", "Sheet1!A1:C3", "R1C1").
377 * Parse @str using the convention associated with @sheet.
378 * Returns a (GnmValue *) of type VALUE_CELLRANGE if the @range was
379 * succesfully parsed or %NULL on failure.
382 value_new_cellrange_str (Sheet
*sheet
, char const *str
)
385 GnmExprParseFlags flags
= GNM_EXPR_PARSE_UNKNOWN_NAMES_ARE_STRINGS
|
386 GNM_EXPR_PARSE_FORCE_EXPLICIT_SHEET_REFERENCES
;
388 g_return_val_if_fail (IS_SHEET (sheet
), NULL
);
389 g_return_val_if_fail (str
!= NULL
, NULL
);
391 parse_pos_init_sheet (&pp
, sheet
);
392 return value_new_cellrange_parsepos_str (&pp
, str
, flags
);
396 * value_new_cellrange_parsepos_str:
397 * @pp: if a relative range is specified, then it will be interpreted relative
398 * to this position (affects only A1-style relative references).
399 * @str: a range specification (ex: "A1", "A1:C3", "Sheet1!A1:C3", "R1C1").
401 * Parse @str using the convention associated with @sheet.
402 * Returns a (GnmValue *) of type VALUE_CELLRANGE if the @range was
403 * succesfully parsed or %NULL on failure.
406 value_new_cellrange_parsepos_str (GnmParsePos
const *pp
, char const *str
,
407 GnmExprParseFlags flags
)
409 GnmExprTop
const *texpr
;
410 GnmConventions
const *convs
= NULL
;
412 g_return_val_if_fail (pp
!= NULL
, NULL
);
413 g_return_val_if_fail (str
!= NULL
, NULL
);
416 convs
= pp
->sheet
->convs
;
418 texpr
= gnm_expr_parse_str (str
, pp
, flags
, convs
, NULL
);
421 GnmValue
*value
= gnm_expr_top_get_range (texpr
);
422 gnm_expr_top_unref (texpr
);
430 value_new_array_non_init (guint cols
, guint rows
)
432 GnmValueArray
*v
= CHUNK_ALLOC (GnmValueArray
, value_array_pool
);
433 *((GnmValueType
*)&(v
->type
)) = VALUE_ARRAY
;
437 v
->vals
= g_new (GnmValue
**, cols
);
438 return (GnmValue
*)v
;
442 value_new_array (guint cols
, guint rows
)
445 GnmValueArray
*v
= (GnmValueArray
*)value_new_array_non_init (cols
, rows
);
447 for (x
= 0; x
< cols
; x
++) {
448 v
->vals
[x
] = g_new (GnmValue
*, rows
);
449 for (y
= 0; y
< rows
; y
++)
450 v
->vals
[x
][y
] = value_new_int (0);
452 return (GnmValue
*)v
;
456 value_new_array_empty (guint cols
, guint rows
)
459 GnmValueArray
*v
= (GnmValueArray
*)value_new_array_non_init (cols
, rows
);
461 for (x
= 0; x
< cols
; x
++) {
462 v
->vals
[x
] = g_new (GnmValue
*, rows
);
463 for (y
= 0; y
< rows
; y
++)
464 v
->vals
[x
][y
] = value_new_empty ();
466 return (GnmValue
*)v
;
470 * Returns TRUE, FALSE, or -1.
473 value_parse_boolean (char const *str
, gboolean translated
)
476 /* FIXME: ascii??? */
477 if (0 == g_ascii_strcasecmp (str
, go_locale_boolean_name (TRUE
)))
479 else if (0 == g_ascii_strcasecmp (str
, go_locale_boolean_name (FALSE
)))
484 if (0 == g_ascii_strcasecmp (str
, "TRUE"))
486 else if (0 == g_ascii_strcasecmp (str
, "FALSE"))
495 value_new_from_string (GnmValueType t
, char const *str
, GOFormat
*sf
,
498 GnmValue
*res
= NULL
;
501 * We need the following cast to avoid a warning from gcc over
502 * VALUE_INTEGER (which is not in GnmValueType).
506 res
= value_new_empty ();
509 case VALUE_BOOLEAN
: {
510 int i
= value_parse_boolean (str
, translated
);
512 res
= value_new_bool ((gboolean
)i
);
521 d
= gnm_strto (str
, &end
);
522 if (d
!= 0 && d
> -GNM_MIN
&& d
< GNM_MIN
)
525 if (str
!= end
&& *end
== '\0' && errno
!= ERANGE
)
526 res
= value_new_float (d
);
532 * Tricky. We are currently storing errors in translated
533 * format, so we might have to undo that.
537 for (i
= 0; i
< G_N_ELEMENTS (standard_errors
); i
++)
538 if (strcmp (standard_errors
[i
].C_name
, str
) == 0) {
539 res
= value_new_error_std (NULL
, (GnmStdError
)i
);
544 res
= value_new_error (NULL
, str
);
548 res
= value_new_string (str
);
552 case VALUE_CELLRANGE
:
554 /* This happen with corrupted files. */
559 value_set_fmt (res
, sf
);
565 * @v: (transfer full) (allow-none): value to dispose of
570 value_release (GnmValue
*value
)
575 if (VALUE_FMT (value
) != NULL
)
576 go_format_unref (VALUE_FMT (value
));
578 switch (value
->v_any
.type
) {
581 /* We did not allocate anything, there is nothing to free */
585 CHUNK_FREE (value_float_pool
, &value
->v_float
);
589 /* Do not release VALUE_TERMINATE, it is a magic number */
590 if (value
== VALUE_TERMINATE
) {
591 g_warning ("Someone freed VALUE_TERMINATE -- shame on them.");
595 go_string_unref (value
->v_err
.mesg
);
596 CHUNK_FREE (value_error_pool
, &value
->v_err
);
600 go_string_unref (value
->v_str
.val
);
601 CHUNK_FREE (value_string_pool
, &value
->v_str
);
605 GnmValueArray
*v
= &value
->v_array
;
608 for (x
= 0; x
< v
->x
; x
++) {
609 for (y
= 0; y
< v
->y
; y
++)
610 value_release (v
->vals
[x
][y
]);
615 CHUNK_FREE (value_array_pool
, v
);
619 case VALUE_CELLRANGE
:
620 CHUNK_FREE (value_range_pool
, &value
->v_range
);
625 * If we don't recognize the type this is probably garbage.
626 * Do not free it to avoid heap corruption
628 g_warning ("value_release problem.");
631 g_assert_not_reached ();
636 * @v: (nullable): #GnmValue
638 * Returns: (transfer full) (nullable): a copy of @v.
641 value_dup (GnmValue
const *src
)
648 switch (src
->v_any
.type
){
650 res
= value_new_empty ();
654 res
= value_new_bool (src
->v_bool
.val
);
658 res
= value_new_float (src
->v_float
.val
);
662 res
= value_new_error_str (NULL
, /* &src->v_err.src, */
667 go_string_ref (src
->v_str
.val
);
668 res
= value_new_string_str (src
->v_str
.val
);
671 case VALUE_CELLRANGE
:
672 res
= value_new_cellrange_unsafe (&src
->v_range
.cell
.a
,
673 &src
->v_range
.cell
.b
);
678 GnmValueArray
*array
= (GnmValueArray
*)value_new_array_non_init (
679 src
->v_array
.x
, src
->v_array
.y
);
681 for (x
= 0; x
< array
->x
; x
++) {
682 array
->vals
[x
] = g_new (GnmValue
*, array
->y
);
683 for (y
= 0; y
< array
->y
; y
++)
684 array
->vals
[x
][y
] = value_dup (src
->v_array
.vals
[x
][y
]);
686 res
= (GnmValue
*)array
;
691 g_warning ("value_dup problem.");
692 res
= value_new_empty ();
694 value_set_fmt (res
, VALUE_FMT (src
));
699 value_compare_real (GnmValue
const *a
, GnmValue
const *b
,
700 gboolean case_sensitive
,
701 gboolean default_locale
);
709 * qsort style comparison function for ascending order
712 value_cmp (void const *ptr_a
, void const *ptr_b
)
714 GnmValue
const *a
= *(GnmValue
const **)ptr_a
;
715 GnmValue
const *b
= *(GnmValue
const **)ptr_b
;
716 switch (value_compare_real (a
, b
, TRUE
, TRUE
)) {
717 case IS_EQUAL
: return 0;
718 case IS_LESS
: return -1;
719 case IS_GREATER
: return 1;
723 return a
->v_any
.type
- b
->v_any
.type
;
731 * qsort style comparison function for descending order.
734 value_cmp_reverse (void const *ptr_a
, void const *ptr_b
)
736 return -value_cmp (ptr_a
, ptr_b
);
740 value_equal (GnmValue
const *a
, GnmValue
const *b
)
742 if (a
->v_any
.type
!= b
->v_any
.type
)
745 switch (a
->v_any
.type
) {
747 return a
->v_bool
.val
== b
->v_bool
.val
;
750 return go_string_equal (a
->v_str
.val
, b
->v_str
.val
);
753 return go_string_equal (a
->v_err
.mesg
, b
->v_err
.mesg
);
756 return a
->v_float
.val
== b
->v_float
.val
;
761 case VALUE_CELLRANGE
:
762 return gnm_cellref_equal (&a
->v_range
.cell
.a
, &b
->v_range
.cell
.a
) &&
763 gnm_cellref_equal (&a
->v_range
.cell
.b
, &b
->v_range
.cell
.b
);
766 if (a
->v_array
.x
== b
->v_array
.x
&& a
->v_array
.y
== b
->v_array
.y
) {
769 for (y
= 0; y
< a
->v_array
.y
; y
++)
770 for (x
= 0; x
< a
->v_array
.x
; x
++)
771 if (!value_equal (a
->v_array
.vals
[x
][y
],
772 b
->v_array
.vals
[x
][y
]))
778 #ifndef DEBUG_SWITCH_ENUM
780 g_assert_not_reached ();
787 value_hash (GnmValue
const *v
)
789 switch (v
->v_any
.type
) {
791 return v
->v_bool
.val
? 0x555aaaa : 0xaaa5555;
794 return go_string_hash (v
->v_str
.val
);
797 return go_string_hash (v
->v_err
.mesg
);
801 gnm_float mant
= gnm_frexp (gnm_abs (v
->v_float
.val
), &expt
);
802 guint h
= ((guint
)(0x80000000u
* mant
)) ^ expt
;
803 if (v
->v_float
.val
>= 0)
811 case VALUE_CELLRANGE
:
812 /* FIXME: take sheet into account? */
813 return (gnm_cellref_hash (&v
->v_range
.cell
.a
) * 3) ^
814 gnm_cellref_hash (&v
->v_range
.cell
.b
);
818 guint h
= (v
->v_array
.x
* 257) ^ (v
->v_array
.y
+ 42);
820 /* For speed, just walk the diagonal. */
821 for (i
= 0; i
< v
->v_array
.x
&& i
< v
->v_array
.y
; i
++) {
823 if (v
->v_array
.vals
[i
][i
])
824 h
^= value_hash (v
->v_array
.vals
[i
][i
]);
829 #ifndef DEBUG_SWITCH_ENUM
831 g_assert_not_reached ();
839 value_type_of (const GnmValue
*v
)
841 return v
->v_any
.type
;
846 value_get_as_bool (GnmValue
const *v
, gboolean
*err
)
854 switch (v
->v_any
.type
) {
859 return v
->v_bool
.val
;
862 int i
= value_parse_boolean (value_peek_string (v
), FALSE
);
872 return v
->v_float
.val
!= 0.0;
875 g_warning ("Unhandled value in value_get_as_bool.");
877 case VALUE_CELLRANGE
:
887 * use only if you are sure the value is ok
890 value_get_as_checked_bool (GnmValue
const *v
)
892 gboolean result
, err
;
894 result
= value_get_as_bool (v
, &err
);
896 g_return_val_if_fail (!err
, FALSE
);
902 * value_get_as_gstring:
905 * @conv: #GnmConventions
907 * A simple value formatter to convert @v into a string stored in @target
908 * according to @conv. See format_value_gstring for something more elaborate
909 * that handles formats too.
912 value_get_as_gstring (GnmValue
const *v
, GString
*target
,
913 GnmConventions
const *conv
)
918 switch (v
->v_any
.type
){
923 GnmStdError e
= value_error_classify (v
);
924 if (e
== GNM_ERROR_UNKNOWN
) {
925 g_string_append_c (target
, '#');
926 go_strescape (target
, v
->v_err
.mesg
->str
);
928 g_string_append (target
, value_error_name (e
, conv
->output
.translated
));
932 case VALUE_BOOLEAN
: {
933 gboolean b
= v
->v_bool
.val
;
934 g_string_append (target
,
935 conv
->output
.translated
936 ? go_locale_boolean_name (b
)
937 : (b
? "TRUE" : "FALSE"));
942 g_string_append (target
, v
->v_str
.val
->str
);
946 if (conv
->output
.decimal_digits
< 0)
947 go_dtoa (target
, "!" GNM_FORMAT_g
, v
->v_float
.val
);
949 g_string_append_printf (target
, "%.*" GNM_FORMAT_g
,
950 conv
->output
.decimal_digits
,
956 gunichar row_sep
, col_sep
;
959 if (conv
->array_row_sep
)
960 row_sep
= conv
->array_row_sep
;
962 row_sep
= go_locale_get_row_sep ();
963 if (conv
->array_col_sep
)
964 col_sep
= conv
->array_col_sep
;
966 col_sep
= go_locale_get_col_sep ();
968 g_string_append_c (target
, '{');
969 for (y
= 0; y
< v
->v_array
.y
; y
++){
971 g_string_append_unichar (target
, row_sep
);
973 for (x
= 0; x
< v
->v_array
.x
; x
++){
974 val
= v
->v_array
.vals
[x
][y
];
977 g_string_append_unichar (target
, col_sep
);
981 /* This is not supposed to happen, but
982 let's not crash anyway. */
983 g_string_append (target
, "?");
984 } else if (VALUE_IS_STRING (val
))
985 go_strescape (target
, val
->v_str
.val
->str
);
987 value_get_as_gstring (val
, target
, conv
);
990 g_string_append_c (target
, '}');
994 case VALUE_CELLRANGE
: {
996 /* Note: this makes only sense for absolute references or
997 * references relative to A1
1000 range_init_value (&range
, v
);
1001 tmp
= global_range_name (v
->v_range
.cell
.a
.sheet
, &range
);
1002 g_string_append (target
, tmp
);
1011 g_assert_not_reached ();
1016 * value_get_as_string:
1019 * Simplistic value rendering
1021 * Returns: (transfer full): a string rendering of @v.
1024 value_get_as_string (GnmValue
const *v
)
1026 GString
*res
= g_string_sized_new (10);
1027 value_get_as_gstring (v
, res
, gnm_conventions_default
);
1028 return g_string_free (res
, FALSE
);
1032 * value_peek_string:
1035 * Returns: (transfer none): A string representation of the value. The
1036 * result will stay valid until either (a) the value is disposed of, or
1037 * (b) two further calls to this function are made.
1039 // NOTE: "(transfer none)" papers over an introspection bug
1041 value_peek_string (GnmValue
const *v
)
1043 g_return_val_if_fail (v
, "");
1045 if (VALUE_IS_STRING (v
))
1046 return v
->v_str
.val
->str
;
1047 else if (VALUE_IS_ERROR (v
))
1048 return v
->v_err
.mesg
->str
;
1050 static char *cache
[2] = { NULL
, NULL
};
1051 static int next
= 0;
1054 g_free (cache
[next
]);
1055 s
= cache
[next
] = value_get_as_string (v
);
1056 next
= (next
+ 1) % G_N_ELEMENTS (cache
);
1065 * Returns: (transfer full): A string representation of the value suitable
1066 * for use in a Python __repr__ function.
1069 value_stringify (GnmValue
const *v
)
1071 GString
*res
= g_string_sized_new (30);
1073 g_string_append_c (res
, '{');
1075 switch (v
->v_any
.type
) {
1077 g_string_append (res
, "EMPTY,");
1078 g_string_append (res
, "None");
1082 g_string_append (res
, "STRING,");
1083 go_strescape (res
, value_peek_string (v
));
1086 case VALUE_CELLRANGE
:
1087 g_string_append (res
, "CELLRANGE,");
1088 g_string_append (res
, value_peek_string (v
));
1092 g_string_append (res
, "ARRAY,");
1093 g_string_append (res
, value_peek_string (v
));
1097 g_string_append (res
, "FLOAT,");
1098 g_string_append (res
, value_peek_string (v
));
1102 g_string_append (res
, "BOOLEAN,");
1103 g_string_append_c (res
, v
->v_bool
.val
? '1' : '0');
1107 g_string_append (res
, "ERROR,");
1108 go_strescape (res
, value_peek_string (v
));
1112 g_string_append (res
, "?,?");
1116 if (VALUE_FMT (v
) != NULL
) {
1117 g_string_append_c (res
, ',');
1118 go_strescape (res
, go_format_as_XL (VALUE_FMT (v
)));
1121 g_string_append_c (res
, '}');
1123 return g_string_free (res
, FALSE
);
1130 * @v: (nullable): a #GnmValue
1132 * Returns: @v interpreted as an integer.
1135 value_get_as_int (GnmValue
const *v
)
1139 switch (v
->v_any
.type
) {
1144 return atoi (v
->v_str
.val
->str
);
1146 case VALUE_CELLRANGE
:
1147 g_warning ("Getting range as a int: what to do?");
1154 return (int) gnm_fake_trunc (v
->v_float
.val
);
1157 return v
->v_bool
.val
? 1 : 0;
1163 g_warning ("value_get_as_int unknown type 0x%x (%d).", v
->v_any
.type
, v
->v_any
.type
);
1170 * value_get_as_float:
1171 * @v: (nullable): a #GnmValue
1173 * Returns: @v interpreted as a floating point value.
1176 value_get_as_float (GnmValue
const *v
)
1181 switch (v
->v_any
.type
) {
1186 return gnm_strto (v
->v_str
.val
->str
, NULL
);
1188 case VALUE_CELLRANGE
:
1189 g_warning ("Getting range as a double: what to do?");
1196 return (gnm_float
) v
->v_float
.val
;
1199 return v
->v_bool
.val
? 1. : 0.;
1205 g_warning ("value_get_as_float type error.");
1212 value_is_zero (GnmValue
const *v
)
1214 return gnm_abs (value_get_as_float (v
)) < 64 * GNM_EPSILON
;
1218 value_get_rangeref (GnmValue
const *v
)
1220 g_return_val_if_fail (VALUE_IS_CELLRANGE (v
), NULL
);
1221 return &v
->v_range
.cell
;
1226 * value_coerce_to_number:
1230 * If the value can be used as a number return that number
1231 * otherwise free it at return an appropriate error
1234 value_coerce_to_number (GnmValue
*v
, gboolean
*valid
, GnmEvalPos
const *ep
)
1236 g_return_val_if_fail (v
!= NULL
, NULL
);
1239 if (VALUE_IS_STRING (v
)) {
1241 format_match_number (value_peek_string (v
), NULL
,
1242 sheet_date_conv (ep
->sheet
));
1245 return value_new_error_VALUE (ep
);
1247 } else if (VALUE_IS_ERROR (v
))
1250 if (!VALUE_IS_NUMBER (v
)) {
1252 return value_new_error_VALUE (ep
);
1260 value_array_set (GnmValue
*array
, int col
, int row
, GnmValue
*v
)
1262 g_return_if_fail (v
);
1263 g_return_if_fail (VALUE_IS_ARRAY (array
));
1264 g_return_if_fail (col
>=0);
1265 g_return_if_fail (row
>=0);
1266 g_return_if_fail (array
->v_array
.y
> row
);
1267 g_return_if_fail (array
->v_array
.x
> col
);
1269 value_release (array
->v_array
.vals
[col
][row
]);
1270 array
->v_array
.vals
[col
][row
] = v
;
1274 compare_bool_bool (GnmValue
const *va
, GnmValue
const *vb
)
1276 gboolean err
; /* Ignored */
1277 gboolean
const a
= value_get_as_bool (va
, &err
);
1278 gboolean
const b
= value_get_as_bool (vb
, &err
);
1280 return b
? IS_EQUAL
: IS_GREATER
;
1281 return b
? IS_LESS
: IS_EQUAL
;
1285 compare_float_float (GnmValue
const *va
, GnmValue
const *vb
)
1287 gnm_float
const a
= value_get_as_float (va
);
1288 gnm_float
const b
= value_get_as_float (vb
);
1298 compare_error_error (GnmValue
const *va
, GnmValue
const *vb
)
1300 GnmStdError ea
= value_error_classify (va
);
1301 GnmStdError eb
= value_error_classify (vb
);
1305 return ea
< eb
? IS_LESS
: IS_GREATER
;
1307 if (ea
!= GNM_ERROR_UNKNOWN
)
1310 /* Two unknown errors. Just compare strings. */
1311 i
= strcmp (value_peek_string (va
), value_peek_string (vb
));
1312 return (i
> 0 ? IS_GREATER
: (i
< 0 ? IS_LESS
: IS_EQUAL
));
1323 * Returns a non-negative difference between 2 values
1326 value_diff (GnmValue
const *a
, GnmValue
const *b
)
1328 GnmValueType ta
, tb
;
1330 /* Handle trivial (including empty/empty) and double NULL */
1334 ta
= VALUE_IS_EMPTY (a
) ? VALUE_EMPTY
: a
->v_any
.type
;
1335 tb
= VALUE_IS_EMPTY (b
) ? VALUE_EMPTY
: b
->v_any
.type
;
1337 /* string > empty */
1338 if (ta
== VALUE_STRING
) {
1340 /* Strings are > (empty, or number) */
1342 if (*a
->v_str
.val
->str
== '\0')
1346 /* If both are strings compare as string */
1348 if (go_string_equal (a
->v_str
.val
, b
->v_str
.val
))
1351 case VALUE_FLOAT
: case VALUE_BOOLEAN
:
1356 } else if (tb
== VALUE_STRING
) {
1358 /* (empty, or number) < String */
1360 if (*b
->v_str
.val
->str
== '\0')
1363 case VALUE_FLOAT
: case VALUE_BOOLEAN
:
1369 /* Booleans > all numbers (Why did excel do this ?? ) */
1370 if (ta
== VALUE_BOOLEAN
&& tb
== VALUE_FLOAT
)
1372 if (tb
== VALUE_BOOLEAN
&& ta
== VALUE_FLOAT
)
1375 switch ((ta
> tb
) ? ta
: tb
) {
1376 case VALUE_EMPTY
: /* Empty Empty compare */
1380 return (compare_bool_bool (a
, b
) == IS_EQUAL
) ? 0. : DBL_MAX
;
1383 gnm_float
const da
= value_get_as_float (a
);
1384 gnm_float
const db
= value_get_as_float (b
);
1385 return gnm_abs (da
- db
);
1388 return TYPE_MISMATCH
;
1393 gnm_string_cmp (gconstpointer gstr_a
, gconstpointer gstr_b
)
1395 return (gstr_a
== gstr_b
)
1397 : g_utf8_collate (((GOString
const *)gstr_a
)->str
,
1398 ((GOString
const *)gstr_b
)->str
);
1402 gnm_string_cmp_ignorecase (gconstpointer gstr_a
, gconstpointer gstr_b
)
1408 if (gstr_a
== gstr_b
)
1411 a
= g_utf8_casefold (((GOString
const *)gstr_a
)->str
, -1);
1412 b
= g_utf8_casefold (((GOString
const *)gstr_b
)->str
, -1);
1414 res
= g_utf8_collate (a
, b
);
1423 /* This depends on the actual values of the enums. */
1424 #define PAIR(ta_,tb_) ((ta_) + (((tb_) >> 3) - 1))
1425 #define CPAIR(ta_,tb_) (1 ? PAIR((ta_),(tb_)) : sizeof (struct { int sanity_check[((ta_) >= (tb_)) * 2 - 1]; } ))
1432 * @case_sensitive: are string comparisons case sensitive.
1437 value_compare_real (GnmValue
const *a
, GnmValue
const *b
,
1438 gboolean case_sensitive
,
1439 gboolean default_locale
)
1441 GnmValueType ta
, tb
;
1445 /* Handle trivial and double NULL case */
1449 ta
= VALUE_IS_EMPTY (a
) ? VALUE_EMPTY
: a
->v_any
.type
;
1450 tb
= VALUE_IS_EMPTY (b
) ? VALUE_EMPTY
: b
->v_any
.type
;
1454 GnmValueType t
= ta
;
1455 GnmValue
const *v
= a
;
1462 switch (PAIR (ta
,tb
)) {
1463 case CPAIR (VALUE_EMPTY
,VALUE_EMPTY
):
1464 /* In most cases this is handled by the trivial case. */
1465 /* We can get here if one of a and b is NULL and the */
1466 /* is not but contains an empty value. */
1469 /* ---------------------------------------- */
1471 case CPAIR (VALUE_BOOLEAN
,VALUE_EMPTY
): /* Blank is FALSE */
1472 case CPAIR (VALUE_BOOLEAN
,VALUE_BOOLEAN
):
1473 res
= compare_bool_bool (a
, b
);
1476 /* ---------------------------------------- */
1478 case CPAIR (VALUE_FLOAT
,VALUE_BOOLEAN
):
1479 /* Number < boolean (Why did excel do this ?? ) */
1482 case CPAIR (VALUE_FLOAT
,VALUE_EMPTY
): /* Blank is 0 */
1483 case CPAIR (VALUE_FLOAT
,VALUE_FLOAT
):
1484 res
= compare_float_float (a
, b
);
1487 /* ---------------------------------------- */
1489 case CPAIR (VALUE_ERROR
,VALUE_EMPTY
):
1490 case CPAIR (VALUE_ERROR
,VALUE_BOOLEAN
):
1491 case CPAIR (VALUE_ERROR
,VALUE_FLOAT
):
1492 /* Error > others */
1496 case CPAIR (VALUE_ERROR
,VALUE_ERROR
):
1497 res
= compare_error_error (a
, b
);
1500 /* ---------------------------------------- */
1502 case CPAIR (VALUE_STRING
,VALUE_EMPTY
): /* Blank is empty string */
1503 /* String > empty, except empty string */
1504 res
= a
->v_str
.val
->str
[0] == '\0' ? IS_EQUAL
: IS_GREATER
;
1507 case CPAIR (VALUE_STRING
,VALUE_BOOLEAN
):
1508 /* String < boolean */
1512 case CPAIR (VALUE_STRING
,VALUE_FLOAT
):
1513 /* String > number */
1517 case CPAIR (VALUE_STRING
,VALUE_ERROR
):
1518 /* String < error */
1522 case CPAIR (VALUE_STRING
,VALUE_STRING
): {
1523 GOString
const *sa
= a
->v_str
.val
;
1524 GOString
const *sb
= b
->v_str
.val
;
1525 int i
= (default_locale
1527 ? go_string_cmp (sa
, sb
)
1528 : go_string_cmp_ignorecase (sa
, sb
))
1530 ? gnm_string_cmp (sa
, sb
)
1531 : gnm_string_cmp_ignorecase (sa
, sb
)));
1532 res
= (i
> 0 ? IS_GREATER
: (i
< 0 ? IS_LESS
: IS_EQUAL
));
1536 /* ---------------------------------------- */
1539 res
= TYPE_MISMATCH
;
1545 else if (res
== IS_GREATER
)
1555 value_compare (GnmValue
const *a
, GnmValue
const *b
, gboolean case_sensitive
)
1557 return value_compare_real (a
, b
, case_sensitive
, TRUE
);
1561 value_compare_no_cache (GnmValue
const *a
, GnmValue
const *b
,
1562 gboolean case_sensitive
)
1564 return value_compare_real (a
, b
, case_sensitive
, FALSE
);
1570 * @fmt: (nullable): #GOFormat
1575 value_set_fmt (GnmValue
*v
, GOFormat
const *fmt
)
1577 if (fmt
== VALUE_FMT (v
))
1579 g_return_if_fail (!VALUE_IS_EMPTY (v
) && !VALUE_IS_BOOLEAN (v
));
1581 go_format_ref (fmt
);
1582 if (VALUE_FMT (v
) != NULL
)
1583 go_format_unref (VALUE_FMT (v
));
1587 /****************************************************************************/
1590 gnm_value_get_type (void)
1595 t
= g_boxed_type_register_static ("GnmValue",
1596 (GBoxedCopyFunc
)value_dup
,
1597 (GBoxedFreeFunc
)value_release
);
1600 /****************************************************************************/
1602 GnmValueErr
const value_terminate_err
= { VALUE_ERROR
, NULL
, NULL
};
1603 static GnmValueFloat
const the_value_zero
= { VALUE_FLOAT
, NULL
, 0 };
1604 GnmValue
const *value_zero
= (GnmValue
const *)&the_value_zero
;
1607 * value_init: (skip)
1614 for (i
= 0; i
< G_N_ELEMENTS (standard_errors
); i
++) {
1615 standard_errors
[i
].locale_name
= _(standard_errors
[i
].C_name
);
1616 standard_errors
[i
].locale_name_str
=
1617 go_string_new (standard_errors
[i
].locale_name
);
1622 go_mem_chunk_new ("value float pool",
1623 sizeof (GnmValueFloat
),
1627 go_mem_chunk_new ("value error pool",
1628 sizeof (GnmValueErr
),
1632 go_mem_chunk_new ("value string pool",
1633 sizeof (GnmValueStr
),
1637 go_mem_chunk_new ("value range pool",
1638 sizeof (GnmValueRange
),
1642 go_mem_chunk_new ("value array pool",
1643 sizeof (GnmValueArray
),
1649 * value_shutdown: (skip)
1652 value_shutdown (void)
1656 for (i
= 0; i
< G_N_ELEMENTS (standard_errors
); i
++) {
1657 go_string_unref (standard_errors
[i
].locale_name_str
);
1658 standard_errors
[i
].locale_name_str
= NULL
;
1662 go_mem_chunk_destroy (value_float_pool
, FALSE
);
1663 value_float_pool
= NULL
;
1665 go_mem_chunk_destroy (value_error_pool
, FALSE
);
1666 value_error_pool
= NULL
;
1668 go_mem_chunk_destroy (value_string_pool
, FALSE
);
1669 value_string_pool
= NULL
;
1671 go_mem_chunk_destroy (value_range_pool
, FALSE
);
1672 value_range_pool
= NULL
;
1674 go_mem_chunk_destroy (value_array_pool
, FALSE
);
1675 value_array_pool
= NULL
;
1677 if (value_allocations
)
1678 g_printerr ("Leaking %d values.\n", value_allocations
);
1682 /****************************************************************************/