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 (&timestamp, as_string)) {
224 			gda_value_set_timestamp (value, &timestamp);
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 (&timestamp, g_value_get_string (src));
1312 	gda_value_set_timestamp (dest, &timestamp);
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  * &lt;value type="gdatype"&gt;value&lt;/value&gt;
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