1 /*
2 * Copyright (C) 2001 - 2003 Rodrigo Moya <rodrigo@gnome-db.org>
3 * Copyright (C) 2002 - 2003 Gonzalo Paniagua Javier <gonzalo@gnome-db.org>
4 * Copyright (C) 2002 Holger Thon <holger.thon@gnome-db.org>
5 * Copyright (C) 2002 - 2013 Vivien Malerba <malerba@gnome-db.org>
6 * Copyright (C) 2002 Zbigniew Chyla <cyba@gnome.pl>
7 * Copyright (C) 2003 Akira TAGOH <tagoh@gnome-db.org>
8 * Copyright (C) 2003 Danilo Schoeneberg <dschoene@src.gnome.org>
9 * Copyright (C) 2003 Laurent Sansonetti <lrz@src.gnome.org>
10 * Copyright (C) 2003 Philippe CHARLIER <p.charlier@chello.be>
11 * Copyright (C) 2004 Andrew Hill <andru@src.gnome.org>
12 * Copyright (C) 2004 Dani Baeyens <daniel.baeyens@hispalinux.es>
13 * Copyright (C) 2004 - 2011 Murray Cumming <murrayc@murrayc.com>
14 * Copyright (C) 2004 Paisa Seeluangsawat <paisa@users.sf.net>
15 * Copyright (C) 2004 Szalai Ferenc <szferi@einstein.ki.iif.hu>
16 * Copyright (C) 2007 Armin Burgmeier <armin@openismus.com>
17 * Copyright (C) 2007 Leonardo Boshell <lb@kmc.com.co>
18 * Copyright (C) 2008 Przemysław Grzegorczyk <pgrzegorczyk@gmail.com>
19 * Copyright (C) 2009 Bas Driessen <bas.driessen@xobas.com>
20 * Copyright (C) 2010 David King <davidk@openismus.com>
21 * Copyright (C) 2010 Jonh Wendell <jwendell@gnome.org>
22 * Copyright (C) 2011 - 2012 Daniel Espinosa <despinosa@src.gnome.org>
23 *
24 * This library is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU Lesser General Public
26 * License as published by the Free Software Foundation; either
27 * version 2 of the License, or (at your option) any later version.
28 *
29 * This library is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
32 * Lesser General Public License for more details.
33 *
34 * You should have received a copy of the GNU Lesser General Public
35 * License along with this library; if not, write to the
36 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
37 * Boston, MA 02110-1301, USA.
38 */
39
40 #include <string.h>
41 #include <stdlib.h>
42 #include <time.h>
43 #include <locale.h>
44 #include <libgda/gda-value.h>
45 #include <libgda/gda-blob-op.h>
46 #include <libgda/gda-util.h>
47 #include <libxml/parser.h>
48 #include <libxml/tree.h>
49 #define __GDA_INTERNAL__
50 #include "dir-blob-op.h"
51
52 #define l_g_value_unset(val) G_STMT_START{ if (G_IS_VALUE (val)) g_value_unset (val); }G_STMT_END
53 #ifdef G_OS_WIN32
54 #define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
55 #endif
56
57 # ifdef GSEAL_ENABLE
58 /**
59 * GdaNumeric: (set-value-func gda_value_set_numeric) (get-value-func gda_value_get_numeric)
60 * @number: a string representing a number
61 * @precision: precision to use when @number is converted (not implemented jet)
62 * @width: not implemented jet
63 *
64 * Holds numbers represented as strings.
65 *
66 * This struct must be considered as opaque. Any access to its members must use its
67 * accessors added since version 5.0.2.
68 *
69 */
70 struct _GdaNumeric {
71 gchar* number; /* stored in the "C" locale, never NULL */
72 glong precision;
73 glong width;
74
75 /*< private >*/
76 gpointer reserved; /* reserved for future usage with GMP (http://gmplib.org/) */
77 };
78 # else
79 #endif
80
81
82
83 static gboolean
set_from_string(GValue * value,const gchar * as_string)84 set_from_string (GValue *value, const gchar *as_string)
85 {
86 gboolean retval;
87 gchar *endptr [1];
88 gdouble dvalue;
89 glong lvalue;
90 gulong ulvalue;
91 GType type;
92
93 g_return_val_if_fail (value, FALSE);
94 if (! G_IS_VALUE (value)) {
95 g_warning ("Can't set value for a G_TYPE_INVALID GValue");
96 return FALSE;
97 }
98 else if (GDA_VALUE_HOLDS_NULL (value)) {
99 g_warning ("Can't set value for a NULL GValue");
100 return FALSE;
101 }
102
103 type = G_VALUE_TYPE (value);
104 g_value_reset (value);
105
106 /* custom transform function */
107 retval = FALSE;
108 if (type == G_TYPE_BOOLEAN) {
109 if ((as_string[0] == 't') || (as_string[0] == 'T')) {
110 g_value_set_boolean (value, TRUE);
111 retval = TRUE;
112 }
113 else if ((as_string[0] == 'f') || (as_string[0] == 'F')) {
114 g_value_set_boolean (value, FALSE);
115 retval = TRUE;
116 }
117 else {
118 gint i;
119 i = atoi (as_string); /* Flawfinder: ignore */
120 g_value_set_boolean (value, i ? TRUE : FALSE);
121 retval = TRUE;
122 }
123 }
124 else if (type == G_TYPE_INT64) {
125 gint64 i64;
126 i64 = g_ascii_strtoll (as_string, endptr, 10);
127 if (*as_string != '\0' && **endptr == '\0'){
128 g_value_set_int64 (value, i64);
129 retval = TRUE;
130 }
131 }
132 else if (type == G_TYPE_UINT64) {
133 guint64 ui64;
134 ui64 = g_ascii_strtoull (as_string, endptr, 10);
135 if (*as_string != '\0' && **endptr == '\0'){
136 g_value_set_uint64 (value, ui64);
137 retval = TRUE;
138 }
139 }
140 else if (type == G_TYPE_INT) {
141 lvalue = strtol (as_string, endptr, 10);
142 if (*as_string != '\0' && **endptr == '\0'){
143 g_value_set_int (value, (gint32) lvalue);
144 retval = TRUE;
145 }
146 }
147 else if (type == G_TYPE_UINT) {
148 ulvalue = strtoul (as_string, endptr, 10);
149 if (*as_string!=0 && **endptr==0) {
150 g_value_set_uint(value,(guint32)ulvalue);
151 retval = TRUE;
152 }
153 }
154 else if (type == GDA_TYPE_SHORT) {
155 lvalue = strtol (as_string, endptr, 10);
156 if (*as_string != '\0' && **endptr == '\0'){
157 gda_value_set_short (value, (gint16) lvalue);
158 retval = TRUE;
159 }
160 }
161 else if (type == GDA_TYPE_USHORT) {
162 ulvalue = strtoul (as_string, endptr, 10);
163 if (*as_string!=0 && **endptr==0) {
164 gda_value_set_ushort(value,(guint16)ulvalue);
165 retval = TRUE;
166 }
167 }
168 else if (type == G_TYPE_CHAR) {
169 lvalue = strtol (as_string, endptr, 10);
170 if (*as_string!=0 && **endptr==0) {
171 g_value_set_schar(value,(gint)lvalue);
172 retval = TRUE;
173 }
174 }
175 else if (type == G_TYPE_UCHAR) {
176 ulvalue = strtoul (as_string,endptr, 10);
177 if (*as_string!=0 && **endptr==0) {
178 g_value_set_uchar(value,(guchar)ulvalue);
179 retval = TRUE;
180 }
181 }
182 else if (type == G_TYPE_FLOAT) {
183 dvalue = g_ascii_strtod (as_string, endptr);
184 if (*as_string != '\0' && **endptr == '\0'){
185 g_value_set_float (value, (gfloat) dvalue);
186 retval = TRUE;
187 }
188 }
189 else if (type == G_TYPE_DOUBLE) {
190 dvalue = g_ascii_strtod (as_string, endptr);
191 if (*as_string != '\0' && **endptr == '\0'){
192 g_value_set_double (value, dvalue);
193 retval = TRUE;
194 }
195 }
196 else if (type == GDA_TYPE_NUMERIC) {
197 GdaNumeric *numeric = gda_numeric_new ();
198 gda_numeric_set_from_string (numeric, as_string);
199 gda_value_set_numeric (value, numeric);
200 gda_numeric_free (numeric);
201 retval = TRUE;
202 }
203 else if (type == G_TYPE_DATE) {
204 GDate *gdate;
205 gdate = g_date_new ();
206
207 if (gda_parse_iso8601_date (gdate, as_string)) {
208 g_value_take_boxed (value, gdate);
209 retval = TRUE;
210 }
211 else
212 g_date_free (gdate);
213 }
214 else if (type == GDA_TYPE_TIME) {
215 GdaTime timegda;
216 if (gda_parse_iso8601_time (&timegda, as_string)) {
217 gda_value_set_time (value, &timegda);
218 retval = TRUE;
219 }
220 }
221 else if (type == GDA_TYPE_TIMESTAMP) {
222 GdaTimestamp timestamp;
223 if (gda_parse_iso8601_timestamp (×tamp, as_string)) {
224 gda_value_set_timestamp (value, ×tamp);
225 retval = TRUE;
226 }
227 }
228 else if (type == GDA_TYPE_NULL) {
229 gda_value_set_null (value);
230 retval = TRUE;
231 }
232 else if (type == G_TYPE_GTYPE) {
233 GType gt;
234 gt = gda_g_type_from_string (as_string);
235 if (gt != G_TYPE_INVALID) {
236 g_value_set_gtype (value, gt);
237 retval = TRUE;
238 }
239 }
240 else if (type == G_TYPE_ULONG)
241 {
242 gulong ulvalue;
243
244 ulvalue = strtoul (as_string, endptr, 10);
245 if (*as_string!=0 && **endptr==0) {
246 g_value_set_ulong (value, ulvalue);
247 retval = TRUE;
248 }
249 }
250 else if (type == G_TYPE_LONG)
251 {
252 glong lvalue;
253
254 lvalue = strtol (as_string, endptr, 10);
255 if (*as_string!=0 && **endptr==0) {
256 g_value_set_long (value, lvalue);
257 retval = TRUE;
258 }
259 }
260 else if (type == GDA_TYPE_BINARY) {
261 GdaBinary *bin;
262 bin = gda_string_to_binary (as_string);
263 if (bin) {
264 gda_value_take_binary (value, bin);
265 retval = TRUE;
266 }
267 }
268 else if (type == GDA_TYPE_BLOB) {
269 GdaBlob *blob;
270 blob = gda_string_to_blob (as_string);
271 if (blob) {
272 gda_value_take_blob (value, blob);
273 retval = TRUE;
274 }
275 }
276 else if (g_value_type_transformable (G_TYPE_STRING, type)) {
277 /* use the GLib type transformation function */
278 GValue *string;
279
280 string = g_new0 (GValue, 1);
281 g_value_init (string, G_TYPE_STRING);
282 g_value_set_string (string, as_string);
283
284 g_value_transform (string, value);
285 gda_value_free (string);
286
287 retval = TRUE;
288 }
289
290 return retval;
291 }
292
293 /*
294 * Register the NULL type in the GType system
295 */
296 static void
string_to_null(const GValue * src,GValue * dest)297 string_to_null (const GValue *src, GValue *dest)
298 {
299 g_return_if_fail (G_VALUE_HOLDS_STRING (src) && GDA_VALUE_HOLDS_NULL (dest));
300 /* Do nothing just a dummy function to register */
301 }
302
303 static void
null_to_string(const GValue * src,GValue * dest)304 null_to_string (const GValue *src, GValue *dest)
305 {
306 g_return_if_fail (G_VALUE_HOLDS_STRING (dest) && GDA_VALUE_HOLDS_NULL (src));
307 g_value_set_string (dest, "NULL");
308 }
309
310 static gpointer
gda_null_copy(G_GNUC_UNUSED gpointer boxed)311 gda_null_copy (G_GNUC_UNUSED gpointer boxed)
312 {
313 return (gpointer) NULL;
314 }
315
316 static void
gda_null_free(G_GNUC_UNUSED gpointer boxed)317 gda_null_free (G_GNUC_UNUSED gpointer boxed)
318 {
319 }
320
321 GType
gda_null_get_type(void)322 gda_null_get_type (void)
323 {
324 static GType type = 0;
325
326 if (G_UNLIKELY (type == 0)) {
327 type = g_boxed_type_register_static ("GdaNull",
328 (GBoxedCopyFunc) gda_null_copy,
329 (GBoxedFreeFunc) gda_null_free);
330
331 g_value_register_transform_func (G_TYPE_STRING,
332 type,
333 string_to_null);
334
335 g_value_register_transform_func (type,
336 G_TYPE_STRING,
337 null_to_string);
338 }
339
340 return type;
341 }
342
343 /*
344 * Register the DEFAULT type in the GType system
345 */
346 static void
string_to_default(const GValue * src,GValue * dest)347 string_to_default (const GValue *src, GValue *dest)
348 {
349 g_return_if_fail (G_VALUE_HOLDS_STRING (src) && GDA_VALUE_HOLDS_DEFAULT (dest));
350 g_value_set_boxed (dest, g_value_get_string (src));
351 }
352
353 static void
default_to_string(const GValue * src,GValue * dest)354 default_to_string (const GValue *src, GValue *dest)
355 {
356 gchar *str;
357 g_return_if_fail (G_VALUE_HOLDS_STRING (dest) && GDA_VALUE_HOLDS_DEFAULT (src));
358 str = (gchar*) g_value_get_boxed (src);
359 g_value_set_string (dest, str);
360 }
361
362 static gpointer
gda_default_copy(G_GNUC_UNUSED gpointer boxed)363 gda_default_copy (G_GNUC_UNUSED gpointer boxed)
364 {
365 if (boxed)
366 return (gpointer) g_strdup (boxed);
367 else
368 return (gpointer) NULL;
369 }
370
371 static void
gda_default_free(G_GNUC_UNUSED gpointer boxed)372 gda_default_free (G_GNUC_UNUSED gpointer boxed)
373 {
374 g_free (boxed);
375 }
376
377 GType
gda_default_get_type(void)378 gda_default_get_type (void)
379 {
380 static GType type = 0;
381
382 if (G_UNLIKELY (type == 0)) {
383 type = g_boxed_type_register_static ("GdaDefault",
384 (GBoxedCopyFunc) gda_default_copy,
385 (GBoxedFreeFunc) gda_default_free);
386
387 g_value_register_transform_func (G_TYPE_STRING,
388 type,
389 string_to_default);
390
391 g_value_register_transform_func (type,
392 G_TYPE_STRING,
393 default_to_string);
394 }
395
396 return type;
397 }
398
399
400 /*
401 * Register the GdaBinary type in the GType system
402 */
403
404 /* Transform a String GValue to a GdaBinary*/
405 static void
string_to_binary(const GValue * src,GValue * dest)406 string_to_binary (const GValue *src, GValue *dest)
407 {
408 GdaBinary *bin;
409 const gchar *as_string;
410
411 g_return_if_fail (G_VALUE_HOLDS_STRING (src) &&
412 GDA_VALUE_HOLDS_BINARY (dest));
413
414 as_string = g_value_get_string (src);
415
416 bin = gda_string_to_binary (as_string);
417 g_return_if_fail (bin);
418 gda_value_take_binary (dest, bin);
419 }
420
421 static void
binary_to_string(const GValue * src,GValue * dest)422 binary_to_string (const GValue *src, GValue *dest)
423 {
424 gchar *str;
425
426 g_return_if_fail (G_VALUE_HOLDS_STRING (dest) &&
427 GDA_VALUE_HOLDS_BINARY (src));
428
429 str = gda_binary_to_string (gda_value_get_binary ((GValue *) src), 0);
430
431 g_value_take_string (dest, str);
432 }
433
434 GType
gda_binary_get_type(void)435 gda_binary_get_type (void)
436 {
437 static GType type = 0;
438
439 if (G_UNLIKELY (type == 0)) {
440 type = g_boxed_type_register_static ("GdaBinary",
441 (GBoxedCopyFunc) gda_binary_copy,
442 (GBoxedFreeFunc) gda_binary_free);
443
444 g_value_register_transform_func (G_TYPE_STRING,
445 type,
446 string_to_binary);
447
448 g_value_register_transform_func (type,
449 G_TYPE_STRING,
450 binary_to_string);
451 }
452
453 return type;
454 }
455
456 /**
457 * gda_binary_copy:
458 * @boxed: source to get a copy from.
459 *
460 * Creates a new #GdaBinary structure from an existing one.
461
462 * Returns: (transfer full): a newly allocated #GdaBinary which contains a copy of information in @boxed.
463 *
464 * Free-function: gda_binary_free
465 */
466 gpointer
gda_binary_copy(gpointer boxed)467 gda_binary_copy (gpointer boxed)
468 {
469 GdaBinary *src = (GdaBinary*) boxed;
470 GdaBinary *copy = NULL;
471
472 g_return_val_if_fail (src, NULL);
473
474 copy = g_new0 (GdaBinary, 1);
475 copy->data = g_memdup (src->data, src->binary_length);
476 copy->binary_length = src->binary_length;
477
478 return copy;
479 }
480
481 /**
482 * gda_binary_free:
483 * @boxed: (transfer full): #GdaBinary to free.
484 *
485 * Deallocates all memory associated to the given #GdaBinary.
486 */
487 void
gda_binary_free(gpointer boxed)488 gda_binary_free (gpointer boxed)
489 {
490 GdaBinary *binary = (GdaBinary*) boxed;
491
492 g_return_if_fail (binary);
493
494 g_free (binary->data);
495 g_free (binary);
496 }
497
498 /*
499 * Register the GdaBlob type in the GType system
500 */
501 /* Transform a String GValue to a GdaBlob*/
502 static void
string_to_blob(const GValue * src,GValue * dest)503 string_to_blob (const GValue *src, GValue *dest)
504 {
505 GdaBlob *blob;
506 const gchar *as_string;
507
508 g_return_if_fail (G_VALUE_HOLDS_STRING (src) &&
509 GDA_VALUE_HOLDS_BLOB (dest));
510
511 as_string = g_value_get_string (src);
512
513 blob = gda_string_to_blob (as_string);
514 g_return_if_fail (blob);
515 gda_value_take_blob (dest, blob);
516 }
517
518 static void
blob_to_string(const GValue * src,GValue * dest)519 blob_to_string (const GValue *src, GValue *dest)
520 {
521 gchar *str;
522
523 g_return_if_fail (G_VALUE_HOLDS_STRING (dest) &&
524 GDA_VALUE_HOLDS_BLOB (src));
525
526 str = gda_blob_to_string ((GdaBlob *) gda_value_get_blob ((GValue *) src), 0);
527
528 g_value_take_string (dest, str);
529 }
530
531 GType
gda_blob_get_type(void)532 gda_blob_get_type (void)
533 {
534 static GType type = 0;
535
536 if (G_UNLIKELY (type == 0)) {
537 type = g_boxed_type_register_static ("GdaBlob",
538 (GBoxedCopyFunc) gda_blob_copy,
539 (GBoxedFreeFunc) gda_blob_free);
540
541 g_value_register_transform_func (G_TYPE_STRING,
542 type,
543 string_to_blob);
544
545 g_value_register_transform_func (type,
546 G_TYPE_STRING,
547 blob_to_string);
548 }
549
550 return type;
551 }
552
553 /**
554 * gda_blob_copy:
555 * @boxed: source to get a copy from.
556 *
557 * Creates a new #GdaBlob structure from an existing one.
558
559 * Returns: (transfer full): a newly allocated #GdaBlob which contains a copy of information in @boxed.
560 *
561 * Free-function: gda_blob_free
562 */
563 gpointer
gda_blob_copy(gpointer boxed)564 gda_blob_copy (gpointer boxed)
565 {
566 GdaBlob *src = (GdaBlob*) boxed;
567 GdaBlob *copy = NULL;
568
569 g_return_val_if_fail (src, NULL);
570
571 copy = g_new0 (GdaBlob, 1);
572 if (((GdaBinary *)src)->data) {
573 ((GdaBinary *)copy)->data = g_memdup (((GdaBinary *)src)->data, ((GdaBinary *)src)->binary_length);
574 ((GdaBinary *)copy)->binary_length = ((GdaBinary *)src)->binary_length;
575 }
576 gda_blob_set_op (copy, src->op);
577
578 return copy;
579 }
580
581 /**
582 * gda_blob_free:
583 * @boxed: (transfer full): #GdaBlob to free.
584 *
585 * Deallocates all memory associated to the given #GdaBlob.
586 */
587 void
gda_blob_free(gpointer boxed)588 gda_blob_free (gpointer boxed)
589 {
590 GdaBlob *blob = (GdaBlob*) boxed;
591
592 g_return_if_fail (blob);
593
594 if (blob->op) {
595 g_object_unref (blob->op);
596 blob->op = NULL;
597 }
598 gda_binary_free ((GdaBinary *) blob);
599 }
600
601 /**
602 * gda_blob_set_op:
603 * @blob: a #GdaBlob value
604 * @op: (nullable): a #GdaBlobOp object, or %NULL
605 *
606 * correctly assigns @op to @blob
607 */
608 void
gda_blob_set_op(GdaBlob * blob,GdaBlobOp * op)609 gda_blob_set_op (GdaBlob *blob, GdaBlobOp *op)
610 {
611 if (blob->op) {
612 g_object_unref (blob->op);
613 blob->op = NULL;
614 }
615 if (op) {
616 g_return_if_fail (GDA_IS_BLOB_OP (op));
617 blob->op = g_object_ref (op);
618 }
619 }
620
621 /*
622 * Register the GdaGeometricPoint type in the GType system
623 */
624 static void
geometric_point_to_string(const GValue * src,GValue * dest)625 geometric_point_to_string (const GValue *src, GValue *dest)
626 {
627 GdaGeometricPoint *point;
628 gchar *str;
629 g_return_if_fail (G_VALUE_HOLDS_STRING (dest) &&
630 GDA_VALUE_HOLDS_GEOMETRIC_POINT (src));
631
632 point = (GdaGeometricPoint *) gda_value_get_geometric_point ((GValue *) src);
633 if (point)
634 str = g_strdup_printf ("(%.*g,%.*g)", DBL_DIG, point->x,
635 DBL_DIG, point->y);
636 else
637 str = g_strdup ("NULL");
638 g_value_take_string (dest, str);
639 }
640
641 /* Transform a String GValue to a GdaGeometricPoint from a string like "(3.2,5.6)" */
642 static void
string_to_geometricpoint(const GValue * src,GValue * dest)643 string_to_geometricpoint (const GValue *src, GValue *dest)
644 {
645 GdaGeometricPoint *point;
646 const gchar *as_string;
647
648 g_return_if_fail (G_VALUE_HOLDS_STRING (src) &&
649 GDA_VALUE_HOLDS_GEOMETRIC_POINT (dest));
650
651 as_string = g_value_get_string (src);
652 point = g_new0 (GdaGeometricPoint, 1);
653
654 as_string++;
655 point->x = atof (as_string);
656 as_string = strchr (as_string, ',');
657 as_string++;
658 point->y = atof (as_string);
659
660 gda_value_set_geometric_point (dest, point);
661 g_free (point);
662 }
663
664 GType
gda_geometricpoint_get_type(void)665 gda_geometricpoint_get_type (void)
666 {
667 static GType type = 0;
668
669 if (G_UNLIKELY (type == 0)) {
670 type = g_boxed_type_register_static ("GdaGeometricPoint",
671 (GBoxedCopyFunc) gda_geometricpoint_copy,
672 (GBoxedFreeFunc) gda_geometricpoint_free);
673
674 g_value_register_transform_func (G_TYPE_STRING,
675 type,
676 string_to_geometricpoint);
677
678 g_value_register_transform_func (type,
679 G_TYPE_STRING,
680 geometric_point_to_string);
681 }
682
683 return type;
684 }
685
686 /**
687 * gda_geometricpoint_copy:
688 *
689 * Returns: (transfer full):
690 */
691 gpointer
gda_geometricpoint_copy(gpointer boxed)692 gda_geometricpoint_copy (gpointer boxed)
693 {
694 GdaGeometricPoint *val = (GdaGeometricPoint*) boxed;
695 GdaGeometricPoint *copy;
696
697 g_return_val_if_fail( val, NULL);
698
699 copy = g_new0 (GdaGeometricPoint, 1);
700 copy->x = val->x;
701 copy->y = val->y;
702
703 return copy;
704 }
705
706 void
gda_geometricpoint_free(gpointer boxed)707 gda_geometricpoint_free (gpointer boxed)
708 {
709 g_free (boxed);
710 }
711
712
713 /*
714 * Register the GdaNumeric type in the GType system
715 */
716 static void
numeric_to_string(const GValue * src,GValue * dest)717 numeric_to_string (const GValue *src, GValue *dest)
718 {
719 const GdaNumeric *numeric;
720
721 g_return_if_fail (G_VALUE_HOLDS_STRING (dest) &&
722 GDA_VALUE_HOLDS_NUMERIC (src));
723
724 numeric = gda_value_get_numeric (src);
725 if (numeric)
726 g_value_set_string (dest, numeric->number);
727 else
728 g_value_set_string (dest, "NULL");
729 }
730
731 static void
numeric_to_int(const GValue * src,GValue * dest)732 numeric_to_int (const GValue *src, GValue *dest)
733 {
734 const GdaNumeric *numeric;
735
736 g_return_if_fail (G_VALUE_HOLDS_INT (dest) &&
737 GDA_VALUE_HOLDS_NUMERIC (src));
738
739 numeric = gda_value_get_numeric (src);
740 if (numeric) {
741 glong tmp;
742 tmp = atol (numeric->number); /* Flawfinder: ignore */
743 if ((tmp < G_MININT) || (tmp > G_MAXINT))
744 g_warning ("Integer overflow for value %ld", tmp);
745 g_value_set_int (dest, tmp);
746 }
747 else
748 g_value_set_int (dest, 0);
749 }
750
751 static void
numeric_to_uint(const GValue * src,GValue * dest)752 numeric_to_uint (const GValue *src, GValue *dest)
753 {
754 const GdaNumeric *numeric;
755
756 g_return_if_fail (G_VALUE_HOLDS_UINT (dest) &&
757 GDA_VALUE_HOLDS_NUMERIC (src));
758
759 numeric = gda_value_get_numeric (src);
760 if (numeric) {
761 glong tmp;
762 tmp = atol (numeric->number); /* Flawfinder: ignore */
763 if ((tmp < 0) || (tmp > (glong)G_MAXUINT))
764 g_warning ("Unsigned integer overflow for value %ld", tmp);
765 g_value_set_uint (dest, tmp);
766 }
767 else
768 g_value_set_uint (dest, 0);
769 }
770
771 static void
numeric_to_boolean(const GValue * src,GValue * dest)772 numeric_to_boolean (const GValue *src, GValue *dest)
773 {
774 const GdaNumeric *numeric;
775
776 g_return_if_fail (G_VALUE_HOLDS_BOOLEAN (dest) &&
777 GDA_VALUE_HOLDS_NUMERIC (src));
778
779 numeric = gda_value_get_numeric (src);
780 if (numeric)
781 g_value_set_boolean (dest, atoi (numeric->number)); /* Flawfinder: ignore */
782 else
783 g_value_set_boolean (dest, 0);
784 }
785
786 static void
numeric_to_double(const GValue * src,GValue * dest)787 numeric_to_double (const GValue *src, GValue *dest)
788 {
789 const GdaNumeric *numeric;
790
791 g_return_if_fail (G_VALUE_HOLDS_DOUBLE (dest) &&
792 GDA_VALUE_HOLDS_NUMERIC (src));
793
794 numeric = gda_value_get_numeric (src);
795 if (numeric)
796 g_value_set_double (dest, gda_numeric_get_double (numeric));
797 else
798 g_value_set_double (dest, 0.0);
799 }
800
801 static void
numeric_to_float(const GValue * src,GValue * dest)802 numeric_to_float (const GValue *src, GValue *dest)
803 {
804 const GdaNumeric *numeric;
805
806 g_return_if_fail (G_VALUE_HOLDS_FLOAT (dest) &&
807 GDA_VALUE_HOLDS_NUMERIC (src));
808
809 numeric = gda_value_get_numeric (src);
810 if (numeric)
811 g_value_set_float (dest, (float) gda_numeric_get_double (numeric));
812 else
813 g_value_set_float (dest, 0.0);
814 }
815
816 GType
gda_numeric_get_type(void)817 gda_numeric_get_type (void)
818 {
819 static GType type = 0;
820
821 if (G_UNLIKELY (type == 0)) {
822 type = g_boxed_type_register_static ("GdaNumeric",
823 (GBoxedCopyFunc) gda_numeric_copy,
824 (GBoxedFreeFunc) gda_numeric_free);
825
826 /* FIXME: No function to Transform String to from GdaNumeric */
827
828 g_value_register_transform_func (type, G_TYPE_STRING, numeric_to_string);
829 g_value_register_transform_func (type, G_TYPE_INT, numeric_to_int);
830 g_value_register_transform_func (type, G_TYPE_UINT, numeric_to_uint);
831 g_value_register_transform_func (type, G_TYPE_BOOLEAN, numeric_to_boolean);
832 g_value_register_transform_func (type, G_TYPE_DOUBLE, numeric_to_double);
833 g_value_register_transform_func (type, G_TYPE_FLOAT, numeric_to_float);
834 }
835
836 return type;
837 }
838
839
840 /**
841 * gda_numeric_copy:
842 * @src: source to get a copy from.
843 *
844 * Creates a new #GdaNumeric structure from an existing one.
845
846 * Returns: (transfer full): a newly allocated #GdaNumeric which contains a copy of information in @boxed.
847 *
848 * Free-function: gda_numeric_free
849 */
850
851 GdaNumeric*
gda_numeric_copy(GdaNumeric * src)852 gda_numeric_copy (GdaNumeric *src)
853 {
854 GdaNumeric *copy;
855 gchar *str;
856
857 g_return_val_if_fail (src, NULL);
858
859 copy = gda_numeric_new ();
860
861 str = gda_numeric_get_string (src);
862 gda_numeric_set_from_string (copy, str);
863 g_free (str);
864
865 gda_numeric_set_width (copy, gda_numeric_get_width (src));
866 gda_numeric_set_precision (copy, gda_numeric_get_precision (src));
867
868 return copy;
869 }
870
871 /**
872 * gda_numeric_free:
873 * @numeric: (transfer full): a #GdaNumeric pointer
874 *
875 * Deallocates all memory associated to the given @boxed
876 */
877 void
gda_numeric_free(GdaNumeric * numeric)878 gda_numeric_free (GdaNumeric *numeric)
879 {
880 g_return_if_fail (numeric);
881
882 g_free (numeric->number);
883 g_free (numeric);
884 }
885
886 static gchar*
gda_dtostr_dup(const double value)887 gda_dtostr_dup (const double value)
888 {
889 char buffer[G_ASCII_DTOSTR_BUF_SIZE];
890 g_ascii_dtostr (buffer, sizeof (buffer), value);
891 return g_strdup (buffer);
892 }
893
894 /**
895 * gda_numeric_new:
896 *
897 * Creates a new #GdaNumeric with defaults.
898 *
899 * Returns: (transfer full): a new #GdaNumeric.
900 * Since: 5.0.2
901 */
902 GdaNumeric*
gda_numeric_new(void)903 gda_numeric_new (void)
904 {
905 GdaNumeric *n = g_new0 (GdaNumeric, 1);
906 n->number = gda_dtostr_dup (0.0);
907 return n;
908 }
909
910 /**
911 * gda_numeric_set_from_string:
912 * @numeric: a #GdaNumeric
913 * @str: a string representing a number, in the C locale format
914 *
915 * Sets @numeric with a number represented by @str, in the C locale format (dot as a fraction separator).
916 *
917 * Since: 5.0.2
918 */
919 void
gda_numeric_set_from_string(GdaNumeric * numeric,const gchar * str)920 gda_numeric_set_from_string (GdaNumeric *numeric, const gchar* str)
921 {
922 g_return_if_fail (numeric);
923 g_return_if_fail (str);
924 g_free (numeric->number);
925
926 gdouble number;
927 gchar *endptr = NULL;
928 number = g_ascii_strtod (str, &endptr);
929 if (*endptr)
930 numeric->number = gda_dtostr_dup (number);
931 else
932 numeric->number = g_strdup (str);
933 }
934
935 /**
936 * gda_numeric_set_double:
937 * @numeric: a #GdaNumeric
938 * @number: a #gdouble
939 *
940 * Sets @numeric using a #gdouble represented by @number.
941 *
942 * Since: 5.0.2
943 */
944 void
gda_numeric_set_double(GdaNumeric * numeric,gdouble number)945 gda_numeric_set_double (GdaNumeric *numeric, gdouble number)
946 {
947 g_return_if_fail (numeric);
948 g_free (numeric->number);
949 numeric->number = gda_dtostr_dup (number);
950 }
951
952 /**
953 * gda_numeric_get_double:
954 * @numeric: a #GdaNumeric
955 *
956 * Returns: a #gdouble representation of @numeric
957 * Since: 5.0.2
958 */
959 gdouble
gda_numeric_get_double(const GdaNumeric * numeric)960 gda_numeric_get_double (const GdaNumeric *numeric)
961 {
962 g_return_val_if_fail (numeric, 0.0);
963 return g_ascii_strtod (numeric->number, NULL);
964 }
965
966 /**
967 * gda_numeric_set_width:
968 * @numeric: a #GdaNumeric
969 * @width: a #glong
970 *
971 * Sets the width of a #GdaNumeric. (Not yet implemented).
972 *
973 * Since: 5.0.2
974 */
975 void
gda_numeric_set_width(GdaNumeric * numeric,glong width)976 gda_numeric_set_width (GdaNumeric *numeric, glong width)
977 {
978 g_return_if_fail (numeric);
979 numeric->width = width;
980 }
981
982 /**
983 * gda_numeric_get_width:
984 * @numeric: a #GdaNumeric
985 *
986 * Gets the width of a #GdaNumeric. (Not yet implemented).
987 *
988 * Returns: an integer with the width of a #GdaNumeric. (Not jet implemented).
989 *
990 * Since: 5.0.2
991 */
992 glong
gda_numeric_get_width(const GdaNumeric * numeric)993 gda_numeric_get_width (const GdaNumeric *numeric)
994 {
995 g_return_val_if_fail (numeric, 0.0);
996 return numeric->width;
997 }
998
999 /**
1000 * gda_numeric_set_precision:
1001 * @numeric: a #GdaNumeric
1002 * @precision: a #glong
1003 *
1004 * Sets the precision of a #GdaNumeric.
1005 *
1006 * Since: 5.0.2
1007 */
1008 void
gda_numeric_set_precision(GdaNumeric * numeric,glong precision)1009 gda_numeric_set_precision (GdaNumeric *numeric, glong precision)
1010 {
1011 g_return_if_fail (numeric);
1012 numeric->precision = precision;
1013 }
1014
1015 /**
1016 * gda_numeric_get_precision:
1017 * @numeric: a #GdaNumeric
1018 *
1019 * Gets the precision of a #GdaNumeric.
1020 *
1021 * Returns: an integer with the precision of a #GdaNumeric.
1022 *
1023 * Since: 5.0.2
1024 */
1025 glong
gda_numeric_get_precision(const GdaNumeric * numeric)1026 gda_numeric_get_precision (const GdaNumeric *numeric)
1027 {
1028 g_return_val_if_fail (numeric, -1);
1029 return numeric->precision;
1030 }
1031 /**
1032 * gda_numeric_get_string:
1033 * @numeric: a #GdaNumeric
1034 *
1035 * Get the string representation of @numeric, in the C locale format (dot as a fraction separator).
1036 *
1037 * Returns: (transfer full) (nullable): a new string representing the stored valued in @numeric
1038 *
1039 * Since: 5.0.2
1040 */
1041 gchar*
gda_numeric_get_string(const GdaNumeric * numeric)1042 gda_numeric_get_string (const GdaNumeric *numeric)
1043 {
1044 if (numeric)
1045 return g_strdup (numeric->number);
1046 else
1047 return NULL;
1048 }
1049
1050 /*
1051 * Register the GdaTime type in the GType system
1052 */
1053
1054 static void
time_to_string(const GValue * src,GValue * dest)1055 time_to_string (const GValue *src, GValue *dest)
1056 {
1057 GdaTime *gdatime;
1058
1059 g_return_if_fail (G_VALUE_HOLDS_STRING (dest) &&
1060 GDA_VALUE_HOLDS_TIME (src));
1061
1062 gdatime = (GdaTime *) gda_value_get_time ((GValue *) src);
1063
1064 if (gdatime) {
1065 GString *string;
1066 string = g_string_new ("");
1067 g_string_append_printf (string, "%02u:%02u:%02u",
1068 gdatime->hour,
1069 gdatime->minute,
1070 gdatime->second);
1071 if (gdatime->fraction != 0)
1072 g_string_append_printf (string, ".%lu", gdatime->fraction);
1073
1074 if (gdatime->timezone != GDA_TIMEZONE_INVALID)
1075 g_string_append_printf (string, "%+02d", (int) gdatime->timezone / 3600);
1076
1077 g_value_take_string (dest, string->str);
1078 g_string_free (string, FALSE);
1079 }
1080 else
1081 g_value_set_string (dest, "NULL");
1082 }
1083
1084 /* Transform a String GValue to a GdaTime from a string like "12:30:15+01" */
1085 static void
string_to_time(const GValue * src,GValue * dest)1086 string_to_time (const GValue *src, GValue *dest)
1087 {
1088 /* FIXME: add more checks*/
1089 GdaTime *timegda;
1090 const gchar *as_string;
1091 const gchar *ptr;
1092
1093 g_return_if_fail (G_VALUE_HOLDS_STRING (src) &&
1094 GDA_VALUE_HOLDS_TIME (dest));
1095
1096 as_string = g_value_get_string (src);
1097 if (!as_string)
1098 return;
1099 timegda = g_new0 (GdaTime, 1);
1100
1101 /* hour */
1102 timegda->timezone = GDA_TIMEZONE_INVALID;
1103 ptr = as_string;
1104 if ((*ptr >= '0') && (*ptr <= '9') &&
1105 (*(ptr+1) >= '0') && (*(ptr+1) <= '9'))
1106 timegda->hour = (*ptr - '0') * 10 + *(ptr+1) - '0';
1107 else {
1108 g_free (timegda);
1109 return;
1110 }
1111
1112 /* minute */
1113 ptr += 2;
1114 if (! *ptr) {
1115 g_free (timegda);
1116 return;
1117 }
1118 if (*ptr == ':')
1119 ptr++;
1120 if ((*ptr >= '0') && (*ptr <= '9') &&
1121 (*(ptr+1) >= '0') && (*(ptr+1) <= '9'))
1122 timegda->minute = (*ptr - '0') * 10 + *(ptr+1) - '0';
1123 else{
1124 g_free (timegda);
1125 return;
1126 }
1127
1128 /* second */
1129 ptr += 2;
1130 timegda->second = 0;
1131 if (! *ptr) {
1132 if ((timegda->hour <= 24) && (timegda->minute <= 60))
1133 gda_value_set_time (dest, timegda);
1134 g_free (timegda);
1135 return;
1136 }
1137 if (*ptr == ':')
1138 ptr++;
1139 if ((*ptr >= '0') && (*ptr <= '9') &&
1140 (*(ptr+1) >= '0') && (*(ptr+1) <= '9'))
1141 timegda->second = (*ptr - '0') * 10 + *(ptr+1) - '0';
1142
1143 /* extra */
1144 ptr += 2;
1145 if (! *ptr) {
1146 if ((timegda->hour <= 24) && (timegda->minute <= 60) &&
1147 (timegda->second <= 60))
1148 gda_value_set_time (dest, timegda);
1149 g_free (timegda);
1150 return;
1151 }
1152
1153 if (*ptr == '.') {
1154 gulong fraction = 0;
1155
1156 ptr ++;
1157 while (*ptr && (*ptr >= '0') && (*ptr <= '9')) {
1158 fraction = fraction * 10 + *ptr - '0';
1159 ptr++;
1160 }
1161 }
1162
1163 if ((*ptr == '+') || (*ptr == '-')) {
1164 glong sign = (*ptr == '+') ? 1 : -1;
1165 timegda->timezone = 0;
1166 while (*ptr && (*ptr >= '0') && (*ptr <= '9')) {
1167 timegda->timezone = timegda->timezone * 10 + sign * ((*ptr) - '0');
1168 ptr++;
1169 }
1170 timegda->timezone *= 3600;
1171 }
1172
1173 /* checks */
1174 if ((timegda->hour <= 24) || (timegda->minute <= 60) || (timegda->second <= 60))
1175 gda_value_set_time (dest, timegda);
1176 g_free (timegda);
1177 }
1178
1179 GType
gda_time_get_type(void)1180 gda_time_get_type(void)
1181 {
1182 static GType type = 0;
1183
1184 if (G_UNLIKELY (type == 0)) {
1185 type = g_boxed_type_register_static ("GdaTime",
1186 (GBoxedCopyFunc) gda_time_copy,
1187 (GBoxedFreeFunc) gda_time_free);
1188
1189 g_value_register_transform_func (G_TYPE_STRING, type, string_to_time);
1190 g_value_register_transform_func (type, G_TYPE_STRING, time_to_string);
1191 }
1192
1193 return type;
1194 }
1195
1196 /**
1197 * gda_time_copy:
1198 *
1199 * Returns: (transfer full):
1200 */
1201 gpointer
gda_time_copy(gpointer boxed)1202 gda_time_copy (gpointer boxed)
1203 {
1204
1205 GdaTime *src = (GdaTime*) boxed;
1206 GdaTime *copy = NULL;
1207
1208 g_return_val_if_fail (src, NULL);
1209
1210 copy = g_new0 (GdaTime, 1);
1211 copy->hour = src->hour;
1212 copy->minute = src->minute;
1213 copy->second = src->second;
1214 copy->fraction = src->fraction;
1215 copy->timezone = src->timezone;
1216
1217 return copy;
1218 }
1219
1220 void
gda_time_free(gpointer boxed)1221 gda_time_free (gpointer boxed)
1222 {
1223 g_free (boxed);
1224 }
1225
1226 /**
1227 * gda_time_valid:
1228 * @time: a #GdaTime value to check if it is valid
1229 *
1230 * Returns: #TRUE if #GdaTime is valid; %FALSE otherwise.
1231 *
1232 * Since: 4.2
1233 */
1234 gboolean
gda_time_valid(const GdaTime * time)1235 gda_time_valid (const GdaTime *time)
1236 {
1237 g_return_val_if_fail (time, FALSE);
1238
1239 if ((time->hour > 23) ||
1240 (time->minute > 59) ||
1241 (time->second > 59))
1242 return FALSE;
1243 if ((time->fraction >= 1000000) ||
1244 (time->timezone <= -12 * 3600) ||
1245 (time->timezone >= 12 * 3600))
1246 return FALSE;
1247 return TRUE;
1248 }
1249
1250 /**
1251 * gda_time_change_timezone:
1252 * @time: a valid #GdaTime
1253 * @ntz: a new timezone to use, in seconds added to GMT
1254 *
1255 * Changes @time's timezone (for example to convert from GMT to another time zone).
1256 * If @time's current timezone is unset (i.e. equal to %GDA_TIMEZONE_INVALID), then this function simply sets
1257 * @time's timezone attribute; Otherwise, it adds or removes hours, minutes or seconds to reflect the time in the new timezone.
1258 *
1259 * Note: the resulting will always be a valid time.
1260 *
1261 * Since: 5.2
1262 */
1263 void
gda_time_change_timezone(GdaTime * time,glong ntz)1264 gda_time_change_timezone (GdaTime *time, glong ntz)
1265 {
1266 g_return_if_fail (time);
1267 g_return_if_fail (gda_time_valid (time));
1268 g_return_if_fail ((ntz > - 12 * 3600) && (ntz < 12 * 3600));
1269
1270 if (time->timezone == ntz)
1271 return;
1272
1273 if (time->timezone != GDA_TIMEZONE_INVALID) {
1274 glong nsec;
1275 nsec = time->hour * 3600 + time->minute * 60 + time->second - time->timezone + ntz;
1276 if (nsec < 0)
1277 nsec += 86400;
1278 else if (nsec >= 86400)
1279 nsec -= 86400;
1280
1281 /* hours */
1282 gint n;
1283 n = nsec / 3600;
1284 time->hour = (gushort) n;
1285
1286 /* minutes */
1287 nsec -= n * 3600;
1288 n = nsec / 60;
1289 time->minute = (gushort) n;
1290
1291 /* seconds */
1292 nsec -= n * 60;
1293 time->second = (gushort) nsec;
1294 }
1295
1296 time->timezone = ntz;
1297 }
1298
1299 /*
1300 * Register the GdaTimestamp type in the GType system
1301 */
1302 /* Transform a String GValue to a GdaTimestamp from a string like "2003-12-13 13:12:01.12+01" */
1303 static void
string_to_timestamp(const GValue * src,GValue * dest)1304 string_to_timestamp (const GValue *src, GValue *dest)
1305 {
1306 GdaTimestamp timestamp;
1307
1308 g_return_if_fail (G_VALUE_HOLDS_STRING (src) &&
1309 GDA_VALUE_HOLDS_TIMESTAMP (dest));
1310
1311 gda_parse_iso8601_timestamp (×tamp, g_value_get_string (src));
1312 gda_value_set_timestamp (dest, ×tamp);
1313 }
1314
1315 static void
timestamp_to_string(const GValue * src,GValue * dest)1316 timestamp_to_string (const GValue *src, GValue *dest)
1317 {
1318 GdaTimestamp *timestamp;
1319
1320 g_return_if_fail (G_VALUE_HOLDS_STRING (dest) &&
1321 GDA_VALUE_HOLDS_TIMESTAMP (src));
1322
1323 timestamp = (GdaTimestamp *) gda_value_get_timestamp ((GValue *) src);
1324 if (timestamp) {
1325 GString *string;
1326 string = g_string_new ("");
1327 g_string_append_printf (string, "%04u-%02u-%02u %02u:%02u:%02u",
1328 timestamp->year,
1329 timestamp->month,
1330 timestamp->day,
1331 timestamp->hour,
1332 timestamp->minute,
1333 timestamp->second);
1334 if (timestamp->fraction > 0)
1335 g_string_append_printf (string, ".%lu", timestamp->fraction);
1336 if (timestamp->timezone != GDA_TIMEZONE_INVALID)
1337 g_string_append_printf (string, "%+02d",
1338 (int) timestamp->timezone/3600);
1339 g_value_take_string (dest, string->str);
1340 g_string_free (string, FALSE);
1341 }
1342 else
1343 g_value_set_string (dest, "NULL");
1344 }
1345
1346 GType
gda_timestamp_get_type(void)1347 gda_timestamp_get_type (void)
1348 {
1349 static GType type = 0;
1350
1351 if (G_UNLIKELY (type == 0)) {
1352 type = g_boxed_type_register_static ("GdaTimestamp",
1353 (GBoxedCopyFunc) gda_timestamp_copy,
1354 (GBoxedFreeFunc) gda_timestamp_free);
1355
1356 g_value_register_transform_func (G_TYPE_STRING, type, string_to_timestamp);
1357 g_value_register_transform_func (type, G_TYPE_STRING, timestamp_to_string);
1358 }
1359
1360 return type;
1361 }
1362
1363 /**
1364 * gda_timestamp_copy:
1365 *
1366 * Returns: (transfer full):
1367 */
1368 gpointer
gda_timestamp_copy(gpointer boxed)1369 gda_timestamp_copy (gpointer boxed)
1370 {
1371 GdaTimestamp *src = (GdaTimestamp*) boxed;
1372 GdaTimestamp *copy;
1373
1374 g_return_val_if_fail(src, NULL);
1375
1376 copy = g_new0 (GdaTimestamp, 1);
1377 copy->year = src->year;
1378 copy->month = src->month;
1379 copy->day = src->day;
1380 copy->hour = src->hour;
1381 copy->minute = src->minute;
1382 copy->second = src->second;
1383 copy->fraction = src->fraction;
1384 copy->timezone = src->timezone;
1385
1386 return copy;
1387 }
1388
1389 void
gda_timestamp_free(gpointer boxed)1390 gda_timestamp_free (gpointer boxed)
1391 {
1392 g_free (boxed);
1393 }
1394
1395 /**
1396 * gda_timestamp_valid:
1397 * @timestamp: a #GdaTimestamp value to check if it is valid
1398 *
1399 * Returns: #TRUE if #GdaTimestamp is valid; %FALSE otherwise.
1400 *
1401 * Since: 4.2
1402 */
1403 gboolean
gda_timestamp_valid(const GdaTimestamp * timestamp)1404 gda_timestamp_valid (const GdaTimestamp *timestamp)
1405 {
1406 g_return_val_if_fail (timestamp, FALSE);
1407
1408 /* check the date part */
1409 if (! g_date_valid_dmy ((GDateDay) timestamp->day, (GDateMonth) timestamp->month,
1410 (GDateYear) timestamp->year))
1411 return FALSE;
1412
1413 /* check the time part */
1414 if ((timestamp->hour > 23) ||
1415 (timestamp->minute > 59) ||
1416 (timestamp->second > 59))
1417 return FALSE;
1418 if ((timestamp->fraction >= 1000000) ||
1419 (timestamp->timezone <= -12 * 3600) ||
1420 (timestamp->timezone >= 12 * 3600))
1421 return FALSE;
1422
1423 return TRUE;
1424 }
1425
1426 /**
1427 * gda_timestamp_change_timezone:
1428 * @ts: a valid #GdaTimestamp
1429 * @ntz: a new timezone to use, in seconds added to GMT
1430 *
1431 * This function is similar to gda_time_change_timezone() but operates on time stamps.
1432 *
1433 * Note: the resulting will always be a valid time.
1434 *
1435 * Since: 5.2
1436 */
1437 void
gda_timestamp_change_timezone(GdaTimestamp * ts,glong ntz)1438 gda_timestamp_change_timezone (GdaTimestamp *ts, glong ntz)
1439 {
1440 g_return_if_fail (ts);
1441 g_return_if_fail (gda_timestamp_valid (ts));
1442 g_return_if_fail ((ntz > - 12 * 3600) && (ntz < 12 * 3600));
1443
1444 if (ts->timezone == ntz)
1445 return;
1446
1447 if (ts->timezone != GDA_TIMEZONE_INVALID) {
1448 glong nsec;
1449 nsec = ts->hour * 3600 + ts->minute * 60 + ts->second - ts->timezone + ntz;
1450 if (nsec < 0) {
1451 GDate *date;
1452 date = g_date_new_dmy ((GDateDay) ts->day, (GDateMonth) ts->month, (GDateYear) ts->year);
1453 g_date_subtract_days (date, 1);
1454 ts->year = g_date_get_year (date);
1455 ts->month = g_date_get_month (date);
1456 ts->day = g_date_get_day (date);
1457 g_date_free (date);
1458 nsec += 86400;
1459 }
1460 else if (nsec >= 86400) {
1461 GDate *date;
1462 date = g_date_new_dmy ((GDateDay) ts->day, (GDateMonth) ts->month, (GDateYear) ts->year);
1463 g_date_add_days (date, 1);
1464 ts->year = g_date_get_year (date);
1465 ts->month = g_date_get_month (date);
1466 ts->day = g_date_get_day (date);
1467 g_date_free (date);
1468 nsec -= 86400;
1469 }
1470
1471 /* hours */
1472 gint n;
1473 n = nsec / 3600;
1474 ts->hour = (gushort) n;
1475
1476 /* minutes */
1477 nsec -= n * 3600;
1478 n = nsec / 60;
1479 ts->minute = (gushort) n;
1480
1481 /* seconds */
1482 nsec -= n * 60;
1483 ts->second = (gushort) nsec;
1484 }
1485
1486 ts->timezone = ntz;
1487 }
1488
1489 /**
1490 * gda_value_new: (skip)
1491 * @type: the new value type.
1492 *
1493 * Makes a new #GValue of type @type.
1494 *
1495 * Returns: (transfer full): the newly created #GValue with the specified @type. You need to set the value in the returned GValue.
1496 *
1497 * Free-function: gda_value_free
1498 */
1499 GValue *
gda_value_new(GType type)1500 gda_value_new (GType type)
1501 {
1502 GValue *value;
1503
1504 value = g_new0 (GValue, 1);
1505 g_value_init (value, type);
1506
1507 return value;
1508 }
1509
1510 /**
1511 * gda_value_new_null: (skip)
1512 *
1513 * Creates a new #GValue initiated to a #GdaNull structure with a #GDA_TYPE_NULL, to
1514 * represent a NULL in the database.
1515 *
1516 * Returns: (transfer full): a new #GValue of the type #GDA_TYPE_NULL
1517 */
1518 GValue*
gda_value_new_null(void)1519 gda_value_new_null (void)
1520 {
1521 return gda_value_new (GDA_TYPE_NULL);
1522 }
1523
1524 /**
1525 * gda_value_new_default: (skip)
1526 * @default_val: (nullable): the default value as a string, or %NULL
1527 *
1528 * Creates a new default value.
1529 *
1530 * Returns: (transfer full): a new #GValue of the type #GDA_TYPE_DEFAULT
1531 *
1532 * Since: 4.2.9
1533 */
1534 GValue *
gda_value_new_default(const gchar * default_val)1535 gda_value_new_default (const gchar *default_val)
1536 {
1537 GValue *value;
1538 value = gda_value_new (GDA_TYPE_DEFAULT);
1539 g_value_set_boxed (value, default_val);
1540 return value;
1541 }
1542
1543 /**
1544 * gda_value_new_binary: (skip)
1545 * @val: value to set for the new #GValue.
1546 * @size: the size of the memory pool pointer to by @val.
1547 *
1548 * Makes a new #GValue of type #GDA_TYPE_BINARY with value @val.
1549 *
1550 * Returns: (transfer full): the newly created #GValue.
1551 *
1552 * Free-function: gda_value_free
1553 */
1554 GValue *
gda_value_new_binary(const guchar * val,glong size)1555 gda_value_new_binary (const guchar *val, glong size)
1556 {
1557 GValue *value;
1558 GdaBinary binary;
1559
1560 /* We use the const on the function parameter to make this clearer,
1561 * but it would be awkward to keep the const in the struct.
1562 */
1563 binary.data = (guchar*)val;
1564 binary.binary_length = size;
1565
1566 value = g_new0 (GValue, 1);
1567 gda_value_set_binary (value, &binary);
1568
1569 return value;
1570 }
1571
1572 /**
1573 * gda_value_new_blob: (skip)
1574 * @val: value to set for the new #GValue.
1575 * @size: the size of the memory pool pointer to by @val.
1576 *
1577 * Makes a new #GValue of type #GDA_TYPE_BLOB with the data contained by @val.
1578 *
1579 * Returns: (transfer full): the newly created #GValue.
1580 *
1581 * Free-function: gda_value_free
1582 */
1583 GValue *
gda_value_new_blob(const guchar * val,glong size)1584 gda_value_new_blob (const guchar *val, glong size)
1585 {
1586 GValue *value;
1587 GdaBlob *blob;
1588 GdaBinary *bin;
1589
1590 blob = g_new0 (GdaBlob, 1);
1591 bin = (GdaBinary*)(blob);
1592 bin->data = g_new (guchar, size);
1593 memcpy ((gpointer) bin->data, (gpointer) val, size); /* Flawfinder: ignore */
1594 bin->binary_length = size;
1595 blob->op = NULL;
1596
1597 value = g_new0 (GValue, 1);
1598 g_value_init (value, GDA_TYPE_BLOB);
1599 g_value_take_boxed (value, blob);
1600
1601 return value;
1602 }
1603
1604 /**
1605 * gda_value_new_blob_from_file: (skip)
1606 * @filename: name of the file to manipulate
1607 *
1608 * Makes a new #GValue of type #GDA_TYPE_BLOB interfacing with the contents of the file
1609 * named @filename
1610 *
1611 * Returns: (transfer full): the newly created #GValue.
1612 *
1613 * Free-function: gda_value_free
1614 */
1615 GValue *
gda_value_new_blob_from_file(const gchar * filename)1616 gda_value_new_blob_from_file (const gchar *filename)
1617 {
1618 GValue *value;
1619 GdaBlob *blob;
1620
1621 blob = g_new0 (GdaBlob, 1);
1622 blob->op = _gda_dir_blob_op_new (filename);
1623
1624 value = g_new0 (GValue, 1);
1625 g_value_init (value, GDA_TYPE_BLOB);
1626 g_value_take_boxed (value, blob);
1627
1628 return value;
1629 }
1630
1631 /*
1632 * Warning: modifies @gmttm and loctm
1633 *
1634 * Returns: the offset, or G_MAXLONG in case of error
1635 */
1636 static glong
compute_tz_offset(struct tm * gmttm,struct tm * loctm)1637 compute_tz_offset (struct tm *gmttm, struct tm *loctm)
1638 {
1639 time_t lt, gt;
1640 if (! gmttm || !loctm)
1641 return G_MAXLONG;
1642
1643 gmttm->tm_isdst = 0;
1644 loctm->tm_isdst = 0;
1645
1646 lt = mktime (loctm);
1647 if (lt == -1)
1648 return G_MAXLONG;
1649 gt = mktime (gmttm);
1650 if (gt == -1)
1651 return G_MAXLONG;
1652
1653 glong off;
1654 off = lt - gt;
1655 if ((off >= 24 * 3600) || (off <= - 24 * 3600))
1656 return G_MAXLONG;
1657 else
1658 return off;
1659 }
1660
1661 /**
1662 * gda_value_new_timestamp_from_timet: (skip)
1663 * @val: value to set for the new #GValue.
1664 *
1665 * Makes a new #GValue of type #GDA_TYPE_TIMESTAMP with value @val
1666 * (of type time_t). The returned timestamp's value is relative to the current
1667 * timezone (i.e. is localtime).
1668 *
1669 * For example, to get a time stamp representing the current date and time, use:
1670 *
1671 * <code>
1672 * ts = gda_value_new_timestamp_from_timet (time (NULL));
1673 * </code>
1674 *
1675 * Returns: (transfer full): the newly created #GValue, or %NULL in case of error
1676 *
1677 * Free-function: gda_value_free
1678 */
1679 GValue *
gda_value_new_timestamp_from_timet(time_t val)1680 gda_value_new_timestamp_from_timet (time_t val)
1681 {
1682 GValue *value = NULL;
1683 struct tm *ltm = NULL;
1684 glong tz = 0;
1685
1686 #ifdef HAVE_LOCALTIME_R
1687 struct tm gmttm, loctm;
1688 tzset ();
1689 ltm = localtime_r ((const time_t *) &val, &loctm);
1690 tz = compute_tz_offset (gmtime_r ((const time_t *) &val, &gmttm), &loctm);
1691 if (tz == G_MAXLONG)
1692 ltm = NULL;
1693 #elif HAVE_LOCALTIME_S
1694 struct tm gmttm, loctm;
1695 if ((localtime_s (&loctm, (const time_t *) &val) == 0) &&
1696 (gmtime_s (&gmttm, (const time_t *) &val) == 0)) {
1697 tz = compute_tz_offset (&gmttm, &loctm);
1698 if (tz != G_MAXLONG)
1699 ltm = &loctm;
1700 }
1701 #else
1702 struct tm gmttm, loctm;
1703 ltm = gmtime ((const time_t *) &val);
1704 if (ltm) {
1705 gmttm = *ltm;
1706 ltm = localtime ((const time_t *) &val);
1707 if (ltm) {
1708 loctm = *ltm;
1709 tz = compute_tz_offset (&gmttm, &loctm);
1710 if (tz == G_MAXLONG)
1711 ltm = NULL;
1712 }
1713 }
1714
1715 #endif
1716
1717 if (ltm) {
1718 GdaTimestamp tstamp;
1719 tstamp.year = ltm->tm_year + 1900;
1720 tstamp.month = ltm->tm_mon + 1;
1721 tstamp.day = ltm->tm_mday;
1722 tstamp.hour = ltm->tm_hour;
1723 tstamp.minute = ltm->tm_min;
1724 tstamp.second = ltm->tm_sec;
1725 tstamp.fraction = 0;
1726 tstamp.timezone = tz;
1727
1728 value = g_new0 (GValue, 1);
1729 gda_value_set_timestamp (value, (const GdaTimestamp *) &tstamp);
1730 }
1731
1732 return value;
1733 }
1734
1735 /**
1736 * gda_value_new_from_string: (skip)
1737 * @as_string: stringified representation of the value.
1738 * @type: the new value type.
1739 *
1740 * Makes a new #GValue of type @type from its string representation.
1741 *
1742 * For more information
1743 * about the string format, see the gda_value_set_from_string() function.
1744 * This function is typically used when reading configuration files or other non-user input that should be locale
1745 * independent.
1746 *
1747 * Returns: (transfer full): the newly created #GValue or %NULL if the string representation cannot be converted to the specified @type.
1748 *
1749 * Free-function: gda_value_free
1750 */
1751 GValue *
gda_value_new_from_string(const gchar * as_string,GType type)1752 gda_value_new_from_string (const gchar *as_string, GType type)
1753 {
1754 GValue *value;
1755
1756 g_return_val_if_fail (as_string, NULL);
1757
1758 value = gda_value_new (type);
1759 if (set_from_string (value, as_string))
1760 return value;
1761 else {
1762 gda_value_free (value);
1763 return NULL;
1764 }
1765 }
1766
1767 /**
1768 * gda_value_new_from_xml: (skip)
1769 * @node: an XML node representing the value.
1770 *
1771 * Creates a GValue from an XML representation of it. That XML
1772 * node corresponds to the following string representation:
1773 * <value type="gdatype">value</value>
1774 *
1775 * For more information
1776 * about the string format, see the gda_value_set_from_string() function.
1777 * This function is typically used when reading configuration files or other non-user input that should be locale
1778 * independent.
1779 *
1780 * Returns: (transfer full): the newly created #GValue.
1781 *
1782 * Free-function: gda_value_free
1783 */
1784 GValue *
gda_value_new_from_xml(const xmlNodePtr node)1785 gda_value_new_from_xml (const xmlNodePtr node)
1786 {
1787 GValue *value;
1788 xmlChar *prop;
1789
1790 g_return_val_if_fail (node, NULL);
1791
1792 /* parse the XML */
1793 if (!node || !(node->name) || (node && strcmp ((gchar*)node->name, "value")))
1794 return NULL;
1795
1796 value = g_new0 (GValue, 1);
1797 prop = xmlGetProp (node, (xmlChar*) "gdatype");
1798 if (prop && !gda_value_set_from_string (value,
1799 (gchar*)xmlNodeGetContent (node),
1800 gda_g_type_from_string ((gchar*) prop))) {
1801 g_free (value);
1802 value = NULL;
1803 }
1804 if (prop)
1805 xmlFree (prop);
1806
1807 return value;
1808 }
1809
1810 /**
1811 * gda_value_free: (skip)
1812 * @value: (transfer full) (nullable): the resource to free (or %NULL)
1813 *
1814 * Deallocates all memory associated to a #GValue.
1815 */
1816 void
gda_value_free(GValue * value)1817 gda_value_free (GValue *value)
1818 {
1819 if (!value)
1820 return;
1821 l_g_value_unset (value);
1822 g_free (value);
1823 }
1824
1825 /**
1826 * gda_value_reset_with_type: (skip)
1827 * @value: the #GValue to be reseted
1828 * @type: the #GType to set to
1829 *
1830 * Resets the #GValue and set a new type to #GType.
1831 */
1832 void
gda_value_reset_with_type(GValue * value,GType type)1833 gda_value_reset_with_type (GValue *value, GType type)
1834 {
1835 g_return_if_fail (value);
1836
1837 if (G_IS_VALUE (value) && (G_VALUE_TYPE (value) == type))
1838 g_value_reset (value);
1839 else {
1840 l_g_value_unset (value);
1841 if (type == G_TYPE_INVALID)
1842 return;
1843 else
1844 g_value_init (value, type);
1845 }
1846 }
1847
1848
1849
1850 /**
1851 * gda_value_is_null: (skip)
1852 * @value: value to test.
1853 *
1854 * Tests if a given @value is of type #GDA_TYPE_NULL.
1855 *
1856 * Returns: a boolean that says whether or not @value is of type #GDA_TYPE_NULL.
1857 */
1858 gboolean
gda_value_is_null(const GValue * value)1859 gda_value_is_null (const GValue *value)
1860 {
1861 g_return_val_if_fail (value, FALSE);
1862 return gda_value_isa (value, GDA_TYPE_NULL);
1863 }
1864
1865 /**
1866 * gda_value_is_number: (skip)
1867 * @value: a #GValue.
1868 *
1869 * Gets whether the value stored in the given #GValue is of numeric type or not.
1870 *
1871 * Returns: %TRUE if a number, %FALSE otherwise.
1872 */
1873 gboolean
gda_value_is_number(const GValue * value)1874 gda_value_is_number (const GValue *value)
1875 {
1876 g_return_val_if_fail (value, FALSE);
1877 if(G_VALUE_HOLDS_INT(value) ||
1878 G_VALUE_HOLDS_INT64(value) ||
1879 G_VALUE_HOLDS_UINT(value) ||
1880 G_VALUE_HOLDS_UINT64(value) ||
1881 G_VALUE_HOLDS_CHAR(value) ||
1882 G_VALUE_HOLDS_UCHAR(value))
1883 return TRUE;
1884 else
1885 return FALSE;
1886 }
1887
1888 /**
1889 * gda_value_copy: (skip)
1890 * @value: value to get a copy from.
1891 *
1892 * Creates a new #GValue from an existing one.
1893 *
1894 * Returns: (transfer full): a newly allocated #GValue with a copy of the data in @value.
1895 *
1896 * Free-function: gda_value_free
1897 */
1898 GValue *
gda_value_copy(const GValue * value)1899 gda_value_copy (const GValue *value)
1900 {
1901 GValue *copy;
1902
1903 g_return_val_if_fail (value, NULL);
1904
1905 copy = g_new0 (GValue, 1);
1906
1907 if (G_IS_VALUE (value)) {
1908 g_value_init (copy, G_VALUE_TYPE (value));
1909 g_value_copy (value, copy);
1910 }
1911
1912 return copy;
1913 }
1914
1915 /**
1916 * gda_value_get_binary: (skip)
1917 * @value: a #GValue whose value we want to get.
1918 *
1919 * Returns: (transfer none): the value stored in @value.
1920 */
1921 const GdaBinary *
gda_value_get_binary(const GValue * value)1922 gda_value_get_binary (const GValue *value)
1923 {
1924 GdaBinary *val;
1925
1926 g_return_val_if_fail (value, NULL);
1927 g_return_val_if_fail (gda_value_isa (value, GDA_TYPE_BINARY), NULL);
1928
1929 val = (GdaBinary*) g_value_get_boxed (value);
1930
1931 return val;
1932 }
1933
1934
1935 /**
1936 * gda_value_set_binary: (skip)
1937 * @value: a #GValue that will store @val.
1938 * @binary: a #GdaBinary structure with the data and its size to be stored in @value.
1939 *
1940 * Stores @val into @value.
1941 */
1942 void
gda_value_set_binary(GValue * value,const GdaBinary * binary)1943 gda_value_set_binary (GValue *value, const GdaBinary *binary)
1944 {
1945 g_return_if_fail (value);
1946
1947 l_g_value_unset (value);
1948 g_value_init (value, GDA_TYPE_BINARY);
1949 if (binary)
1950 g_value_set_boxed (value, binary);
1951 else {
1952 GdaBinary bin = {NULL, 0};
1953 g_value_set_boxed (value, &bin);
1954 }
1955 }
1956
1957 /**
1958 * gda_value_take_binary: (skip)
1959 * @value: a #GValue that will store @val.
1960 * @binary: (transfer full): a #GdaBinary structure with the data and its size to be stored in @value.
1961 *
1962 * Stores @val into @value, but on the contrary to gda_value_set_binary(), the @binary
1963 * argument is not copied, but used as-is and it should be considered owned by @value.
1964 */
1965 void
gda_value_take_binary(GValue * value,GdaBinary * binary)1966 gda_value_take_binary (GValue *value, GdaBinary *binary)
1967 {
1968 g_return_if_fail (value);
1969 g_return_if_fail (binary);
1970
1971 l_g_value_unset (value);
1972 g_value_init (value, GDA_TYPE_BINARY);
1973 g_value_take_boxed (value, binary);
1974 }
1975
1976 /**
1977 * gda_value_set_blob: (skip)
1978 * @value: a #GValue that will store @val.
1979 * @blob: a #GdaBlob structure with the data and its size to be stored in @value.
1980 *
1981 * Stores @val into @value.
1982 */
1983 void
gda_value_set_blob(GValue * value,const GdaBlob * blob)1984 gda_value_set_blob (GValue *value, const GdaBlob *blob)
1985 {
1986 g_return_if_fail (value);
1987 g_return_if_fail (blob);
1988
1989 l_g_value_unset (value);
1990 g_value_init (value, GDA_TYPE_BLOB);
1991 g_value_set_boxed (value, blob);
1992 }
1993
1994 /**
1995 * gda_value_get_blob: (skip)
1996 * @value: a #GValue whose value we want to get.
1997 *
1998 * Returns: (transfer none): the value stored in @value.
1999 */
2000 const GdaBlob *
gda_value_get_blob(const GValue * value)2001 gda_value_get_blob (const GValue *value)
2002 {
2003 GdaBlob *val;
2004
2005 g_return_val_if_fail (value, NULL);
2006 g_return_val_if_fail (gda_value_isa (value, GDA_TYPE_BLOB), NULL);
2007
2008 val = (GdaBlob*) g_value_get_boxed (value);
2009
2010 return val;
2011 }
2012
2013 /**
2014 * gda_value_take_blob: (skip)
2015 * @value: a #GValue that will store @val.
2016 * @blob: (transfer full): a #GdaBlob structure with the data and its size to be stored in @value.
2017 *
2018 * Stores @val into @value, but on the contrary to gda_value_set_blob(), the @blob
2019 * argument is not copied, but used as-is and it should be considered owned by @value.
2020 */
2021 void
gda_value_take_blob(GValue * value,GdaBlob * blob)2022 gda_value_take_blob (GValue *value, GdaBlob *blob)
2023 {
2024 g_return_if_fail (value);
2025 g_return_if_fail (blob);
2026
2027 l_g_value_unset (value);
2028 g_value_init (value, GDA_TYPE_BLOB);
2029 g_value_take_boxed (value, blob);
2030 }
2031
2032 /**
2033 * gda_value_get_geometric_point: (skip)
2034 * @value: a #GValue whose value we want to get.
2035 *
2036 * Returns: (transfer none): the value stored in @value.
2037 */
2038 const GdaGeometricPoint *
gda_value_get_geometric_point(const GValue * value)2039 gda_value_get_geometric_point (const GValue *value)
2040 {
2041 g_return_val_if_fail (value, NULL);
2042 g_return_val_if_fail (gda_value_isa (value, GDA_TYPE_GEOMETRIC_POINT), NULL);
2043 return (const GdaGeometricPoint *) g_value_get_boxed(value);
2044 }
2045
2046 /**
2047 * gda_value_set_geometric_point: (skip)
2048 * @value: a #GValue that will store @val.
2049 * @val: value to be stored in @value.
2050 *
2051 * Stores @val into @value.
2052 */
2053 void
gda_value_set_geometric_point(GValue * value,const GdaGeometricPoint * val)2054 gda_value_set_geometric_point (GValue *value, const GdaGeometricPoint *val)
2055 {
2056 g_return_if_fail (value);
2057 g_return_if_fail (val);
2058
2059 l_g_value_unset (value);
2060 g_value_init (value, GDA_TYPE_GEOMETRIC_POINT);
2061 g_value_set_boxed (value, val);
2062 }
2063
2064 /**
2065 * gda_value_set_null: (skip)
2066 * @value: a #GValue that will store a value of type #GDA_TYPE_NULL.
2067 *
2068 * Sets the type of @value to #GDA_TYPE_NULL.
2069 */
2070 void
gda_value_set_null(GValue * value)2071 gda_value_set_null (GValue *value)
2072 {
2073 g_return_if_fail (value);
2074 gda_value_reset_with_type (value, GDA_TYPE_NULL);
2075 }
2076
2077 /**
2078 * gda_value_get_numeric: (skip)
2079 * @value: a #GValue whose value we want to get.
2080 *
2081 * Returns: (transfer none): the value stored in @value.
2082 */
2083 const GdaNumeric *
gda_value_get_numeric(const GValue * value)2084 gda_value_get_numeric (const GValue *value)
2085 {
2086 g_return_val_if_fail (value, NULL);
2087 g_return_val_if_fail (gda_value_isa (value, GDA_TYPE_NUMERIC), NULL);
2088 return (const GdaNumeric *) g_value_get_boxed(value);
2089 }
2090
2091 /**
2092 * gda_value_set_numeric: (skip)
2093 * @value: a #GValue that will store @val.
2094 * @val: value to be stored in @value.
2095 *
2096 * Stores @val into @value.
2097 */
2098 void
gda_value_set_numeric(GValue * value,const GdaNumeric * val)2099 gda_value_set_numeric (GValue *value, const GdaNumeric *val)
2100 {
2101 g_return_if_fail (value);
2102 g_return_if_fail (val);
2103
2104 l_g_value_unset (value);
2105 g_value_init (value, GDA_TYPE_NUMERIC);
2106 g_value_set_boxed (value, val);
2107 }
2108
2109 /**
2110 * gda_value_get_short: (skip)
2111 * @value: a #GValue whose value we want to get.
2112 *
2113 * Returns: the value stored in @value.
2114 */
2115 gshort
gda_value_get_short(const GValue * value)2116 gda_value_get_short (const GValue *value)
2117 {
2118 g_return_val_if_fail (value, -1);
2119 g_return_val_if_fail (gda_value_isa (value, GDA_TYPE_SHORT), -1);
2120 return (gshort) value->data[0].v_int;
2121 }
2122
2123 /**
2124 * gda_value_set_short: (skip)
2125 * @value: a #GValue that will store @val.
2126 * @val: value to be stored in @value.
2127 *
2128 * Stores @val into @value.
2129 */
2130 void
gda_value_set_short(GValue * value,gshort val)2131 gda_value_set_short (GValue *value, gshort val)
2132 {
2133 g_return_if_fail (value);
2134
2135 l_g_value_unset (value);
2136 g_value_init (value, GDA_TYPE_SHORT);
2137 value->data[0].v_int = val;
2138 }
2139
2140 /**
2141 * gda_value_get_ushort: (skip)
2142 * @value: a #GValue whose value we want to get.
2143 *
2144 * Returns: the value stored in @value.
2145 */
2146 gushort
gda_value_get_ushort(const GValue * value)2147 gda_value_get_ushort (const GValue *value)
2148 {
2149 g_return_val_if_fail (value, -1);
2150 g_return_val_if_fail (gda_value_isa (value, GDA_TYPE_USHORT), -1);
2151 return (gushort) value->data[0].v_uint;
2152 }
2153
2154 /**
2155 * gda_value_set_ushort: (skip)
2156 * @value: a #GValue that will store @val.
2157 * @val: value to be stored in @value.
2158 *
2159 * Stores @val into @value.
2160 */
2161 void
gda_value_set_ushort(GValue * value,gushort val)2162 gda_value_set_ushort (GValue *value, gushort val)
2163 {
2164 g_return_if_fail (value);
2165
2166 l_g_value_unset (value);
2167 g_value_init (value, GDA_TYPE_USHORT);
2168 value->data[0].v_uint = val;
2169 }
2170
2171
2172 /**
2173 * gda_value_get_time: (skip)
2174 * @value: a #GValue whose value we want to get.
2175 *
2176 * Returns: (transfer none): the value stored in @value.
2177 */
2178 const GdaTime *
gda_value_get_time(const GValue * value)2179 gda_value_get_time (const GValue *value)
2180 {
2181 g_return_val_if_fail (value, NULL);
2182 g_return_val_if_fail (gda_value_isa (value, GDA_TYPE_TIME), NULL);
2183 return (const GdaTime *) g_value_get_boxed(value);
2184 }
2185
2186 /**
2187 * gda_value_set_time: (skip)
2188 * @value: a #GValue that will store @val.
2189 * @val: value to be stored in @value.
2190 *
2191 * Stores @val into @value.
2192 */
2193 void
gda_value_set_time(GValue * value,const GdaTime * val)2194 gda_value_set_time (GValue *value, const GdaTime *val)
2195 {
2196 g_return_if_fail (value);
2197 g_return_if_fail (val);
2198
2199 l_g_value_unset (value);
2200 g_value_init (value, GDA_TYPE_TIME);
2201 g_value_set_boxed (value, val);
2202 }
2203
2204 /**
2205 * gda_value_get_timestamp: (skip)
2206 * @value: a #GValue whose value we want to get.
2207 *
2208 * Returns: (transfer none): the value stored in @value.
2209 */
2210 const GdaTimestamp *
gda_value_get_timestamp(const GValue * value)2211 gda_value_get_timestamp (const GValue *value)
2212 {
2213 g_return_val_if_fail (value, NULL);
2214 g_return_val_if_fail (gda_value_isa (value, GDA_TYPE_TIMESTAMP), NULL);
2215 return (const GdaTimestamp *) g_value_get_boxed(value);
2216 }
2217
2218 /**
2219 * gda_value_set_timestamp: (skip)
2220 * @value: a #GValue that will store @val.
2221 * @val: value to be stored in @value.
2222 *
2223 * Stores @val into @value.
2224 */
2225 void
gda_value_set_timestamp(GValue * value,const GdaTimestamp * val)2226 gda_value_set_timestamp (GValue *value, const GdaTimestamp *val)
2227 {
2228 g_return_if_fail (value);
2229 g_return_if_fail (val);
2230
2231 l_g_value_unset (value);
2232 g_value_init (value, GDA_TYPE_TIMESTAMP);
2233 g_value_set_boxed (value, val);
2234 }
2235
2236 /**
2237 * gda_value_set_from_string: (skip)
2238 * @value: a #GValue that will store @val.
2239 * @as_string: the stringified representation of the value.
2240 * @type: the type of the value
2241 *
2242 * Stores the value data from its string representation as @type.
2243 *
2244 * The accepted formats are:
2245 * <itemizedlist>
2246 * <listitem><para>G_TYPE_BOOLEAN: a caseless comparison is made with "true" or "false"</para></listitem>
2247 * <listitem><para>numerical types: C locale format (dot as a fraction separator)</para></listitem>
2248 * <listitem><para>G_TYPE_DATE: see <link linkend="gda-parse-iso8601-date">gda_parse_iso8601_date()</link></para></listitem>
2249 * <listitem><para>GDA_TYPE_TIME: see <link linkend="gda-parse-iso8601-time">gda_parse_iso8601_time()</link></para></listitem>
2250 * <listitem><para>GDA_TYPE_TIMESTAMP: see <link linkend="gda-parse-iso8601-timestamp">gda_parse_iso8601_timestamp()</link></para></listitem>
2251 * </itemizedlist>
2252 *
2253 * This function is typically used when reading configuration files or other non-user input that should be locale
2254 * independent.
2255 *
2256 * Returns: %TRUE if the value has been converted to @type from
2257 * its string representation; it not means that the value is converted
2258 * successfully, just that the transformation is available. %FALSE otherwise.
2259 */
2260 gboolean
gda_value_set_from_string(GValue * value,const gchar * as_string,GType type)2261 gda_value_set_from_string (GValue *value,
2262 const gchar *as_string,
2263 GType type)
2264 {
2265 g_return_val_if_fail (value, FALSE);
2266 g_return_val_if_fail (as_string, FALSE);
2267
2268 /* REM: glib does not register any transform function from G_TYPE_STRING to any other
2269 * type except to a G_TYPE_STRING, so we can't use g_value_type_transformable (G_TYPE_STRING, type) */
2270 gda_value_reset_with_type (value, type);
2271 return set_from_string (value, as_string);
2272 }
2273
2274 /**
2275 * gda_value_set_from_value: (skip)
2276 * @value: a #GValue.
2277 * @from: the value to copy from.
2278 *
2279 * Sets the value of a #GValue from another #GValue. This
2280 * is different from #gda_value_copy, which creates a new #GValue.
2281 * #gda_value_set_from_value, on the other hand, copies the contents
2282 * of @copy into @value, which must already be allocated.
2283 *
2284 * If values are incompatible (see @g_value_type_compatible) then @value is set to a
2285 * #GDA_TYPE_NULL, and %FALSE is returned.
2286 *
2287 * Returns: %TRUE if successful, %FALSE otherwise.
2288 */
2289 gboolean
gda_value_set_from_value(GValue * value,const GValue * from)2290 gda_value_set_from_value (GValue *value, const GValue *from)
2291 {
2292 g_return_val_if_fail (value, FALSE);
2293 g_return_val_if_fail (from, FALSE);
2294
2295 if (G_IS_VALUE (from)) {
2296 if (g_value_type_compatible (G_VALUE_TYPE (from), G_VALUE_TYPE (value))) {
2297 g_value_reset (value);
2298 g_value_copy (from, value);
2299 return TRUE;
2300 }
2301 else {
2302 gda_value_set_null (value);
2303 return FALSE;
2304 }
2305 }
2306 else {
2307 l_g_value_unset (value);
2308 return TRUE;
2309 }
2310 }
2311
2312 /**
2313 * gda_value_stringify:
2314 * @value: a #GValue.
2315 *
2316 * Converts a GValue to its string representation which is a human readable value. Note that the
2317 * returned string does not take into account the current locale of the user (on the contrary to the
2318 * #GdaDataHandler objects). Using this function should be limited to debugging and values serialization
2319 * purposes.
2320 *
2321 * Output is in the "C" locale for numbers, and dates are converted in a YYYY-MM-DD format.
2322 *
2323 * Returns: (transfer full): a new string, or %NULL if the conversion cannot be done. Free the value with a g_free() when you've finished using it.
2324 */
2325 gchar *
gda_value_stringify(const GValue * value)2326 gda_value_stringify (const GValue *value)
2327 {
2328 if (!value)
2329 return g_strdup ("NULL");
2330
2331 GType type = G_VALUE_TYPE (value);
2332 if (type == G_TYPE_FLOAT) {
2333 char buffer[G_ASCII_DTOSTR_BUF_SIZE];
2334 g_ascii_formatd (buffer, sizeof (buffer), "%f", g_value_get_float (value));
2335 return g_strdup (buffer);
2336 }
2337 else if (type == G_TYPE_DOUBLE) {
2338 char buffer[G_ASCII_DTOSTR_BUF_SIZE];
2339 g_ascii_formatd (buffer, sizeof (buffer), "%f", g_value_get_double (value));
2340 return g_strdup (buffer);
2341 }
2342 else if (type == GDA_TYPE_NUMERIC) {
2343 gchar *str = gda_numeric_get_string (gda_value_get_numeric (value));
2344 if (str == NULL) {
2345 str = g_strdup ("NULL");
2346 }
2347 return str;
2348 }
2349 else if (type == G_TYPE_DATE) {
2350 GDate *date;
2351 date = (GDate *) g_value_get_boxed (value);
2352 if (date) {
2353 if (g_date_valid (date))
2354 return g_strdup_printf ("%04u-%02u-%02u",
2355 g_date_get_year (date),
2356 g_date_get_month (date),
2357 g_date_get_day (date));
2358 else
2359 return g_strdup_printf ("%04u-%02u-%02u",
2360 date->year, date->month, date->day);
2361 }
2362 else
2363 return g_strdup ("NULL");
2364 }
2365 else if (g_value_type_transformable (G_VALUE_TYPE (value), G_TYPE_STRING)) {
2366 GValue *string;
2367 gchar *str;
2368
2369 string = g_value_init (g_new0 (GValue, 1), G_TYPE_STRING);
2370 g_value_transform (value, string);
2371 str = g_value_dup_string (string);
2372 gda_value_free (string);
2373 return str;
2374 }
2375 else if (G_TYPE_IS_OBJECT (type)) {
2376 GObject *obj;
2377 obj = g_value_get_object (value);
2378 return g_strdup_printf ("%p (%s)", obj, G_OBJECT_TYPE_NAME (obj));
2379 }
2380 else
2381 return g_strdup ("");
2382 }
2383
2384 /**
2385 * gda_value_differ:
2386 * @value1: a #GValue to compare.
2387 * @value2: the other #GValue to be compared to @value1.
2388 *
2389 * Tells if two values are equal or not, by comparing memory representations. Unlike gda_value_compare(),
2390 * the returned value is boolean, and gives no idea about ordering.
2391 *
2392 * The two values must be of the same type, with the exception that a value of any type can be
2393 * compared to a GDA_TYPE_NULL value, specifically:
2394 * <itemizedlist>
2395 * <listitem><para>if @value1 and @value2 are both GDA_TYPE_NULL values then the returned value is 0</para></listitem>
2396 * <listitem><para>if @value1 is a GDA_TYPE_NULL value and @value2 is of another type then the returned value is 1</para></listitem>
2397 * <listitem><para>if @value1 is of another type and @value2 is a GDA_TYPE_NULL value then the returned value is 1</para></listitem>
2398 * <listitem><para>in all other cases, @value1 and @value2 must be of the same type and their values are compared</para></listitem>
2399 * </itemizedlist>
2400 *
2401 * Returns: a non 0 value if @value1 and @value2 differ, and 0 if they are equal
2402 */
2403 gint
gda_value_differ(const GValue * value1,const GValue * value2)2404 gda_value_differ (const GValue *value1, const GValue *value2)
2405 {
2406 GType type;
2407 g_return_val_if_fail (value1 && value2, FALSE);
2408
2409 /* blind value comparison */
2410 type = G_VALUE_TYPE (value1);
2411 if (!bcmp (value1, value2, sizeof (GValue)))
2412 return 0;
2413
2414 /* handle GDA_TYPE_NULL comparisons with other types */
2415 else if (type == GDA_TYPE_NULL) {
2416 if (G_VALUE_TYPE (value2) == GDA_TYPE_NULL)
2417 return 0;
2418 else
2419 return 1;
2420 }
2421
2422 else if (G_VALUE_TYPE (value2) == GDA_TYPE_NULL)
2423 return 1;
2424
2425 g_return_val_if_fail (G_VALUE_TYPE (value1) == G_VALUE_TYPE (value2), 1);
2426
2427 /* general case */
2428 if (type == GDA_TYPE_BINARY) {
2429 const GdaBinary *binary1 = gda_value_get_binary (value1);
2430 const GdaBinary *binary2 = gda_value_get_binary (value2);
2431 if (binary1 && binary2 && (binary1->binary_length == binary2->binary_length))
2432 return bcmp (binary1->data, binary2->data, binary1->binary_length);
2433 else
2434 return 1;
2435 }
2436
2437 else if (type == GDA_TYPE_BLOB) {
2438 const GdaBlob *blob1 = gda_value_get_blob (value1);
2439 const GdaBlob *blob2 = gda_value_get_blob (value2);
2440 if (blob1 && blob2 && (((GdaBinary *)blob1)->binary_length == ((GdaBinary *)blob2)->binary_length)) {
2441 if (blob1->op == blob2->op)
2442 return bcmp (((GdaBinary *)blob1)->data, ((GdaBinary *)blob2)->data,
2443 ((GdaBinary *)blob1)->binary_length);
2444 }
2445 return 1;
2446 }
2447
2448 else if (type == G_TYPE_DATE) {
2449 GDate *d1, *d2;
2450
2451 d1 = (GDate *) g_value_get_boxed (value1);
2452 d2 = (GDate *) g_value_get_boxed (value2);
2453 if (d1 && d2)
2454 return g_date_compare (d1, d2);
2455 return 1;
2456 }
2457
2458 else if (type == GDA_TYPE_GEOMETRIC_POINT) {
2459 const GdaGeometricPoint *p1, *p2;
2460 p1 = gda_value_get_geometric_point (value1);
2461 p2 = gda_value_get_geometric_point (value2);
2462 if (p1 && p2)
2463 return bcmp (p1, p2, sizeof (GdaGeometricPoint));
2464 return 1;
2465 }
2466
2467 else if (type == G_TYPE_OBJECT) {
2468 if (g_value_get_object (value1) == g_value_get_object (value2))
2469 return 0;
2470 else
2471 return -1;
2472 }
2473
2474 else if (type == GDA_TYPE_NUMERIC) {
2475 const GdaNumeric *num1, *num2;
2476 num1= gda_value_get_numeric (value1);
2477 num2 = gda_value_get_numeric (value2);
2478 if (num1 && num2)
2479 return strcmp (num1->number, num2->number);
2480 return 1;
2481 }
2482
2483 else if (type == G_TYPE_STRING) {
2484 const gchar *str1, *str2;
2485 str1 = g_value_get_string (value1);
2486 str2 = g_value_get_string (value2);
2487 if (str1 && str2)
2488 return strcmp (str1, str2);
2489 return 1;
2490 }
2491
2492 else if (type == GDA_TYPE_TIME) {
2493 const GdaTime *t1, *t2;
2494 t1 = gda_value_get_time (value1);
2495 t2 = gda_value_get_time (value2);
2496 if (t1 && t2)
2497 return bcmp (t1, t2, sizeof (GdaTime));
2498 return 1;
2499 }
2500
2501 else if (type == GDA_TYPE_TIMESTAMP) {
2502 const GdaTimestamp *ts1, *ts2;
2503 ts1 = gda_value_get_timestamp (value1);
2504 ts2 = gda_value_get_timestamp (value2);
2505 if (ts1 && ts2)
2506 return bcmp (ts1, ts2, sizeof (GdaTimestamp));
2507 return 1;
2508 }
2509
2510 else if ((type == G_TYPE_INT) ||
2511 (type == G_TYPE_UINT) ||
2512 (type == G_TYPE_INT64) ||
2513 (type == G_TYPE_UINT64) ||
2514 (type == GDA_TYPE_SHORT) ||
2515 (type == GDA_TYPE_USHORT) ||
2516 (type == G_TYPE_FLOAT) ||
2517 (type == G_TYPE_DOUBLE) ||
2518 (type == G_TYPE_BOOLEAN) ||
2519 (type == G_TYPE_CHAR) ||
2520 (type == G_TYPE_UCHAR) ||
2521 (type == G_TYPE_LONG) ||
2522 (type == G_TYPE_ULONG) ||
2523 (type == G_TYPE_GTYPE))
2524 /* values here ARE different because otherwise the bcmp() at the beginning would
2525 * already have retruned */
2526 return 1;
2527
2528 else if (g_type_is_a (type, G_TYPE_OBJECT)) {
2529 if (g_value_get_object (value1) == g_value_get_object (value2))
2530 return 0;
2531 else
2532 return -1;
2533 }
2534
2535 g_warning ("%s() cannot handle values of type %s", __FUNCTION__, g_type_name (G_VALUE_TYPE (value1)));
2536
2537 return 1;
2538 }
2539
2540 /**
2541 * gda_value_compare:
2542 * @value1: a #GValue to compare (not %NULL)
2543 * @value2: the other #GValue to be compared to @value1 (not %NULL)
2544 *
2545 * Compares two values of the same type, with the exception that a value of any type can be
2546 * compared to a GDA_TYPE_NULL value, specifically:
2547 * <itemizedlist>
2548 * <listitem><para>if @value1 and @value2 are both GDA_TYPE_NULL values then the returned value is 0</para></listitem>
2549 * <listitem><para>if @value1 is a GDA_TYPE_NULL value and @value2 is of another type then the returned value is -1</para></listitem>
2550 * <listitem><para>if @value1 is of another type and @value2 is a GDA_TYPE_NULL value then the returned value is 1</para></listitem>
2551 * <listitem><para>in all other cases, @value1 and @value2 must be of the same type and their values are compared</para></listitem>
2552 * </itemizedlist>
2553 *
2554 * Returns: if both values have the same type, returns 0 if both contain
2555 * the same value, an integer less than 0 if @value1 is less than @value2 or
2556 * an integer greater than 0 if @value1 is greater than @value2.
2557 */
2558 gint
gda_value_compare(const GValue * value1,const GValue * value2)2559 gda_value_compare (const GValue *value1, const GValue *value2)
2560 {
2561 gint retval;
2562 GType type;
2563
2564 g_return_val_if_fail (value1 && value2, -1);
2565
2566 type = G_VALUE_TYPE (value1);
2567
2568 if (value1 == value2)
2569 return 0;
2570
2571 /* handle GDA_TYPE_NULL comparisons with other types */
2572 else if (type == GDA_TYPE_NULL) {
2573 if (G_VALUE_TYPE (value2) == GDA_TYPE_NULL)
2574 return 0;
2575 else
2576 return -1;
2577 }
2578
2579 else if (G_VALUE_TYPE (value2) == GDA_TYPE_NULL)
2580 return 1;
2581
2582 /* general case */
2583 g_return_val_if_fail (G_VALUE_TYPE (value1) == G_VALUE_TYPE (value2), -1);
2584
2585 if (type == G_TYPE_INT64) {
2586 gint64 i1 = g_value_get_int64 (value1);
2587 gint64 i2 = g_value_get_int64 (value2);
2588 return (i1 > i2) ? 1 : ((i1 == i2) ? 0 : -1);
2589 }
2590
2591 else if (type == G_TYPE_UINT64) {
2592 guint64 i1 = g_value_get_uint64 (value1);
2593 guint64 i2 = g_value_get_uint64 (value2);
2594 return (i1 > i2) ? 1 : ((i1 == i2) ? 0 : -1);
2595 }
2596
2597 else if (type == GDA_TYPE_BINARY) {
2598 const GdaBinary *binary1 = gda_value_get_binary (value1);
2599 const GdaBinary *binary2 = gda_value_get_binary (value2);
2600 if (binary1 && binary2 && (binary1->binary_length == binary2->binary_length))
2601 return memcmp (binary1->data, binary2->data, binary1->binary_length) ;
2602 else
2603 return -1;
2604 }
2605
2606 else if (type == G_TYPE_BOOLEAN)
2607 return g_value_get_boolean (value1) - g_value_get_boolean (value2);
2608
2609 else if (type == GDA_TYPE_BLOB) {
2610 const GdaBlob *blob1 = gda_value_get_blob (value1);
2611 const GdaBlob *blob2 = gda_value_get_blob (value2);
2612 if (blob1 && blob2 && (((GdaBinary *)blob1)->binary_length == ((GdaBinary *)blob2)->binary_length)) {
2613 if (blob1->op == blob2->op)
2614 return memcmp (((GdaBinary *)blob1)->data, ((GdaBinary *)blob2)->data,
2615 ((GdaBinary *)blob1)->binary_length);
2616 else
2617 return -1;
2618 }
2619 else
2620 return -1;
2621 }
2622
2623 else if (type == G_TYPE_DATE) {
2624 GDate *d1, *d2;
2625
2626 d1 = (GDate *) g_value_get_boxed (value1);
2627 d2 = (GDate *) g_value_get_boxed (value2);
2628 if (d1 && d2)
2629 return g_date_compare (d1, d2);
2630 else {
2631 if (d1)
2632 return 1;
2633 else {
2634 if (d2)
2635 return -1;
2636 else
2637 return 0;
2638 }
2639 }
2640 }
2641
2642 else if (type == G_TYPE_DOUBLE) {
2643 gdouble v1, v2;
2644
2645 v1 = g_value_get_double (value1);
2646 v2 = g_value_get_double (value2);
2647
2648 if (v1 == v2)
2649 return 0;
2650 else
2651 return (v1 > v2) ? 1 : -1;
2652 }
2653
2654 else if (type == GDA_TYPE_GEOMETRIC_POINT) {
2655 const GdaGeometricPoint *p1, *p2;
2656 p1 = gda_value_get_geometric_point (value1);
2657 p2 = gda_value_get_geometric_point (value2);
2658 if (p1 && p2)
2659 return memcmp (p1, p2, sizeof (GdaGeometricPoint));
2660 else if (p1)
2661 return 1;
2662 else if (p2)
2663 return -1;
2664 else
2665 return 0;
2666 }
2667
2668 else if (type == G_TYPE_OBJECT) {
2669 if (g_value_get_object (value1) == g_value_get_object (value2))
2670 return 0;
2671 else
2672 return -1;
2673 }
2674
2675 else if (type == G_TYPE_INT)
2676 return g_value_get_int (value1) - g_value_get_int (value2);
2677
2678 else if (type == GDA_TYPE_NUMERIC) {
2679 const GdaNumeric *num1, *num2;
2680 num1= gda_value_get_numeric (value1);
2681 num2 = gda_value_get_numeric (value2);
2682 if (num1) {
2683 if (num2)
2684 retval = strcmp (num1->number, num2->number);
2685 else
2686 retval = 1;
2687 }
2688 else
2689 retval = -1;
2690 return retval;
2691 }
2692
2693 else if (type == G_TYPE_FLOAT) {
2694 gfloat f1 = g_value_get_float (value1);
2695 gfloat f2 = g_value_get_float (value2);
2696 return (f1 > f2) ? 1 : ((f1 == f2) ? 0 : -1);
2697 }
2698
2699 else if (type == GDA_TYPE_SHORT) {
2700 gshort i1 = gda_value_get_short (value1);
2701 gshort i2 = gda_value_get_short (value2);
2702 return (i1 > i2) ? 1 : ((i1 == i2) ? 0 : -1);
2703 }
2704
2705 else if (type == G_TYPE_ULONG) {
2706 gulong i1 = g_value_get_ulong (value1);
2707 gulong i2 = g_value_get_ulong (value2);
2708 return (i1 > i2) ? 1 : ((i1 == i2) ? 0 : -1);
2709 }
2710
2711 else if (type == G_TYPE_LONG) {
2712 glong i1 = g_value_get_long (value1);
2713 glong i2 = g_value_get_long (value2);
2714 return (i1 > i2) ? 1 : ((i1 == i2) ? 0 : -1);
2715 }
2716
2717 else if (type == GDA_TYPE_USHORT) {
2718 gushort i1 = gda_value_get_ushort (value1);
2719 gushort i2 = gda_value_get_ushort (value2);
2720 return (i1 > i2) ? 1 : ((i1 == i2) ? 0 : -1);
2721 }
2722
2723 else if (type == G_TYPE_STRING) {
2724 const gchar *str1, *str2;
2725 str1 = g_value_get_string (value1);
2726 str2 = g_value_get_string (value2);
2727 if (str1 && str2)
2728 retval = strcmp (str1, str2);
2729 else {
2730 if (str1)
2731 return 1;
2732 else {
2733 if (str2)
2734 return -1;
2735 else
2736 return 0;
2737 }
2738 }
2739
2740 return retval;
2741 }
2742
2743 else if (type == GDA_TYPE_TIME) {
2744 const GdaTime *t1, *t2;
2745 t1 = gda_value_get_time (value1);
2746 t2 = gda_value_get_time (value2);
2747 if (t1 && t2)
2748 return memcmp (t1, t2, sizeof (GdaTime));
2749 else if (t1)
2750 return 1;
2751 else if (t2)
2752 return -1;
2753 else
2754 return 0;
2755 }
2756
2757 else if (type == GDA_TYPE_TIMESTAMP) {
2758 const GdaTimestamp *ts1, *ts2;
2759 ts1 = gda_value_get_timestamp (value1);
2760 ts2 = gda_value_get_timestamp (value2);
2761 if (ts1 && ts2)
2762 return memcmp (ts1, ts2, sizeof (GdaTimestamp));
2763 else if (ts1)
2764 return 1;
2765 else if (ts2)
2766 return -1;
2767 else
2768 return 0;
2769 }
2770
2771 else if (type == G_TYPE_CHAR) {
2772 gint8 c1 = g_value_get_schar (value1);
2773 gint8 c2 = g_value_get_schar (value2);
2774 return (c1 > c2) ? 1 : ((c1 == c2) ? 0 : -1);
2775 }
2776
2777 else if (type == G_TYPE_UCHAR) {
2778 guchar c1 = g_value_get_uchar (value1);
2779 guchar c2 = g_value_get_uchar (value2);
2780 return (c1 > c2) ? 1 : ((c1 == c2) ? 0 : -1);
2781 }
2782
2783 else if (type == G_TYPE_UINT) {
2784 guint i1 = g_value_get_uint (value1);
2785 guint i2 = g_value_get_uint (value2);
2786 return (i1 > i2) ? 1 : ((i1 == i2) ? 0 : -1);
2787 }
2788
2789 else if (type == G_TYPE_GTYPE) {
2790 GType t1 = g_value_get_gtype (value1);
2791 GType t2 = g_value_get_gtype (value2);
2792 return (t1 > t2) ? 1 : ((t1 == t2) ? 0: -1);
2793 }
2794
2795 else if (g_type_is_a (type, G_TYPE_OBJECT)) {
2796 if (g_value_get_object (value1) == g_value_get_object (value2))
2797 return 0;
2798 else
2799 return -1;
2800 }
2801
2802 g_warning ("%s() cannot handle values of type %s", __FUNCTION__, g_type_name (G_VALUE_TYPE (value1)));
2803
2804 return 0;
2805 }
2806
2807 /*
2808 * to_string
2809 *
2810 * The exact reverse process of set_from_string(), almost the same as gda_value_stingify ()
2811 * because of some localization with gda_value_stingify ().
2812 */
2813 static gchar *
to_string(const GValue * value)2814 to_string (const GValue *value)
2815 {
2816 gchar *retval = NULL;
2817
2818 g_return_val_if_fail (value, NULL);
2819
2820 if (G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) {
2821 if (g_value_get_boolean (value))
2822 retval = g_strdup ("true");
2823 else
2824 retval = g_strdup ("false");
2825 }
2826 else
2827 retval = gda_value_stringify (value);
2828
2829 return retval;
2830 }
2831
2832
2833 /**
2834 * gda_value_to_xml: (skip)
2835 * @value: a #GValue.
2836 *
2837 * Serializes the given #GValue to an XML node string.
2838 *
2839 * Returns: (transfer full): the XML node. Once not needed anymore, you should free it.
2840 */
2841 xmlNodePtr
gda_value_to_xml(const GValue * value)2842 gda_value_to_xml (const GValue *value)
2843 {
2844 gchar *valstr;
2845 xmlNodePtr retval;
2846
2847 g_return_val_if_fail (value, NULL);
2848
2849 valstr = to_string (value);
2850
2851 retval = xmlNewNode (NULL, (xmlChar*)"value");
2852 xmlSetProp(retval, (xmlChar*)"type", (xmlChar*)g_type_name (G_VALUE_TYPE (value)));
2853 xmlNodeSetContent (retval, (xmlChar*)valstr);
2854
2855 g_free (valstr);
2856
2857 return retval;
2858 }
2859
2860
2861 /* Register the GDA Types */
2862
2863 /* Gda gshort type */
2864 /* Transform a String GValue to a gshort*/
2865 static void
string_to_short(const GValue * src,GValue * dest)2866 string_to_short(const GValue *src, GValue *dest)
2867 {
2868
2869 const gchar *as_string;
2870 long int lvalue;
2871 gchar *endptr;
2872
2873 g_return_if_fail (G_VALUE_HOLDS_STRING (src) &&
2874 (GDA_VALUE_HOLDS_SHORT (dest) || GDA_VALUE_HOLDS_USHORT (dest)));
2875
2876 as_string = g_value_get_string ((GValue *) src);
2877
2878 lvalue = strtol (as_string, &endptr, 10);
2879
2880 if (*as_string != '\0' && *endptr == '\0') {
2881 if (GDA_VALUE_HOLDS_SHORT (dest))
2882 gda_value_set_short (dest, (gshort) lvalue);
2883 else
2884 gda_value_set_ushort (dest, (gushort) lvalue);
2885 }
2886 }
2887
2888 static void
short_to_string(const GValue * src,GValue * dest)2889 short_to_string (const GValue *src, GValue *dest)
2890 {
2891 gchar *str;
2892
2893 g_return_if_fail (G_VALUE_HOLDS_STRING (dest) &&
2894 (GDA_VALUE_HOLDS_SHORT (src) || GDA_VALUE_HOLDS_USHORT (src)));
2895
2896 if (GDA_VALUE_HOLDS_SHORT (src))
2897 str = g_strdup_printf ("%d", gda_value_get_short ((GValue *) src));
2898 else
2899 str = g_strdup ("NULL");
2900
2901 g_value_take_string (dest, str);
2902 }
2903
2904
2905 GType
gda_short_get_type(void)2906 gda_short_get_type (void)
2907 {
2908 static GType type = 0;
2909
2910 if (G_UNLIKELY (type == 0)) {
2911 static const GTypeInfo type_info = {
2912 0, /* class_size */
2913 NULL, /* base_init */
2914 NULL, /* base_finalize */
2915 NULL, /* class_init */
2916 NULL, /* class_finalize */
2917 NULL, /* class_data */
2918 0, /* instance_size */
2919 0, /* n_preallocs */
2920 NULL, /* instance_init */
2921 NULL /* value_table */
2922 };
2923
2924 type = g_type_register_static (G_TYPE_INT, "GdaShort", &type_info, 0);
2925
2926 g_value_register_transform_func(G_TYPE_STRING,
2927 type,
2928 string_to_short);
2929
2930 g_value_register_transform_func(type,
2931 G_TYPE_STRING,
2932 short_to_string);
2933 }
2934
2935
2936
2937 return type;
2938 }
2939
2940 GType
gda_ushort_get_type(void)2941 gda_ushort_get_type (void) {
2942 static GType type = 0;
2943
2944 if (G_UNLIKELY (type == 0)) {
2945 static const GTypeInfo type_info = {
2946 0, /* class_size */
2947 NULL, /* base_init */
2948 NULL, /* base_finalize */
2949 NULL, /* class_init */
2950 NULL, /* class_finalize */
2951 NULL, /* class_data */
2952 0, /* instance_size */
2953 0, /* n_preallocs */
2954 NULL, /* instance_init */
2955 NULL /* value_table */
2956 };
2957
2958 type = g_type_register_static (G_TYPE_UINT, "GdaUShort", &type_info, 0);
2959
2960 g_value_register_transform_func (G_TYPE_STRING,
2961 type,
2962 string_to_short);
2963
2964 g_value_register_transform_func (type,
2965 G_TYPE_STRING,
2966 short_to_string);
2967 }
2968
2969 return type;
2970 }
2971
2972
2973
2974 #define MYMIN(a,b) (((b) > 0) ? ((a) < (b) ? (a) : (b)) : (a))
2975
2976 /**
2977 * gda_binary_to_string:
2978 * @bin: a correctly filled @GdaBinary structure
2979 * @maxlen: a maximum len used to truncate, or %0 for no maximum length
2980 *
2981 * Converts all the non printable characters of bin->data into the "\xyz" representation
2982 * where "xyz" is the octal representation of the byte, and the '\' (backslash) character
2983 * is converted to "\\". Printable characters (defined by g_ascii_isprint()) as well as newline
2984 * character are not converted.
2985 *
2986 * Note that the backslash and newline characters are considered as printable characters and
2987 * will not be represented by the "\xyz" representation.
2988 *
2989 * Use this function to get a representation as much readable by humans as possible of a binary
2990 * chunk. Note that this function is internally called when transforming a binary value to
2991 * a string for example when using g_value_transform() or gda_value_stringify().
2992 *
2993 * Returns: (transfer full): a new string from @bin
2994 */
2995 gchar *
gda_binary_to_string(const GdaBinary * bin,guint maxlen)2996 gda_binary_to_string (const GdaBinary *bin, guint maxlen)
2997 {
2998 gint nb_rewrites = 0;
2999 gchar *sptr, *rptr;
3000 gulong realsize = MYMIN ((gulong)(bin->binary_length), maxlen);
3001
3002 gchar *retval;
3003 gulong offset = 0;
3004
3005 if (!bin->data || (bin->binary_length == 0))
3006 return g_strdup ("");
3007
3008 /* compute number of char rewrites */
3009 for (offset = 0, sptr = (gchar*) bin->data;
3010 offset < realsize;
3011 offset ++, sptr++) {
3012 if ((*sptr != '\n') && ((*sptr == '\\') || !g_ascii_isprint (*sptr)))
3013 nb_rewrites++;
3014 }
3015
3016 /* mem allocation and copy */
3017 retval = g_malloc0 (realsize + nb_rewrites * 4 + 1);
3018 rptr = retval;
3019 sptr = (gchar*) bin->data;
3020 offset = 0;
3021 while (offset < realsize) {
3022 /* g_print (">%x<\n", (guchar) *ptr); */
3023 if ((*sptr == '\n') || ((*sptr != '\\') && g_ascii_isprint (*sptr))) {
3024 *rptr = *sptr;
3025 rptr ++;
3026 }
3027 else {
3028 if (*sptr == '\\') {
3029 *rptr = '\\';
3030 rptr++;
3031 *rptr = '\\';
3032 rptr++;
3033 }
3034 else {
3035 guchar val = *sptr;
3036
3037 *rptr = '\\';
3038 rptr++;
3039
3040 *rptr = val / 64 + '0';
3041 rptr++;
3042 val = val % 64;
3043
3044 *rptr = val / 8 + '0';
3045 val = val % 8;
3046 rptr++;
3047
3048 *rptr = val + '0';
3049 rptr++;
3050 }
3051 }
3052
3053 sptr++;
3054 offset ++;
3055 }
3056
3057 return retval;
3058 }
3059
3060 /**
3061 * gda_string_to_binary:
3062 * @str: (nullable): a string to convert, or %NULL
3063 *
3064 * Performs the reverse of gda_binary_to_string() (note that for any "\xyz" succession
3065 * of 4 characters where "xyz" represents a valid octal value, the resulting read value will
3066 * be modulo 256).
3067 *
3068 * I @str is %NULL, then an empty (i.e. where the @data part is %NULL) #GdaBinary is created and returned.
3069 *
3070 * Returns: (transfer full): a new #GdaBinary if no error were found in @str, or %NULL otherwise
3071 */
3072 GdaBinary *
gda_string_to_binary(const gchar * str)3073 gda_string_to_binary (const gchar *str)
3074 {
3075 GdaBinary *bin;
3076 glong len = 0, total;
3077 const guchar *sptr;
3078 guchar *rptr, *retval;
3079
3080 if (!str) {
3081 bin = g_new0 (GdaBinary, 1);
3082 bin->data = NULL;
3083 bin->binary_length = 0;
3084 return bin;
3085 }
3086
3087 total = strlen (str);
3088 retval = g_new0 (guchar, total + 1);
3089 sptr = (guchar*) str;
3090 rptr = retval;
3091
3092 while (*sptr) {
3093 if (*sptr == '\\') {
3094 if (*(sptr+1) == '\\') {
3095 *rptr = '\\';
3096 sptr += 2;
3097 }
3098 else {
3099 guint tmp;
3100 if ((*(sptr+1) >= '0') && (*(sptr+1) <= '7') &&
3101 (*(sptr+2) >= '0') && (*(sptr+2) <= '7') &&
3102 (*(sptr+3) >= '0') && (*(sptr+3) <= '7')) {
3103 tmp = (*(sptr+1) - '0') * 64 +
3104 (*(sptr+2) - '0') * 8 +
3105 (*(sptr+3) - '0');
3106 sptr += 4;
3107 *rptr = tmp % 256;
3108 }
3109 else {
3110 g_free (retval);
3111 return NULL;
3112 }
3113 }
3114 }
3115 else {
3116 *rptr = *sptr;
3117 sptr++;
3118 }
3119
3120 rptr++;
3121 len ++;
3122 }
3123
3124 bin = g_new0 (GdaBinary, 1);
3125 bin->data = retval;
3126 bin->binary_length = len;
3127
3128 return bin;
3129 }
3130
3131 /**
3132 * gda_blob_to_string:
3133 * @blob: a correctly filled @GdaBlob structure
3134 * @maxlen: a maximum len used to truncate, or 0 for no maximum length
3135 *
3136 * Converts all the non printable characters of blob->data into the \xxx representation
3137 * where xxx is the octal representation of the byte, and the '\' (backslash) character
3138 * is converted to "\\".
3139 *
3140 * Returns: (transfer full): a new string from @blob
3141 */
3142 gchar *
gda_blob_to_string(GdaBlob * blob,guint maxlen)3143 gda_blob_to_string (GdaBlob *blob, guint maxlen)
3144 {
3145 if (!((GdaBinary *)blob)->data && blob->op) {
3146 /* fetch some data first (limited amount of data) */
3147 gda_blob_op_read (blob->op, blob, 0, 40);
3148 }
3149 return gda_binary_to_string ((GdaBinary*) blob, maxlen);
3150 }
3151
3152 /**
3153 * gda_string_to_blob:
3154 * @str: a string to convert
3155 *
3156 * Performs the reverse of gda_blob_to_string().
3157 *
3158 * Returns: (transfer full): a new #gdaBlob if no error were found in @str, or NULL otherwise
3159 */
3160 GdaBlob *
gda_string_to_blob(const gchar * str)3161 gda_string_to_blob (const gchar *str)
3162 {
3163 GdaBinary *bin;
3164 bin = gda_string_to_binary (str);
3165 if (bin) {
3166 GdaBlob *blob;
3167 blob = g_new0 (GdaBlob, 1);
3168 ((GdaBinary*) blob)->data = bin->data;
3169 ((GdaBinary*) blob)->binary_length = bin->binary_length;
3170 blob->op = NULL;
3171 g_free (bin);
3172 return blob;
3173 }
3174 else
3175 return NULL;
3176 }
3177