Moving files to packaging and extracing new tarball.
[profile/ivi/glib2.git] / gobject / gvalue.c
1 /* GObject - GLib Type, Object, Parameter and Signal Library
2  * Copyright (C) 1997-1999, 2000-2001 Tim Janik and Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General
15  * Public License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * FIXME: MT-safety
22  */
23
24 #include "config.h"
25
26 #include <string.h>
27
28 #include "gvalue.h"
29 #include "gvaluecollector.h"
30 #include "gbsearcharray.h"
31 #include "gtype-private.h"
32
33
34 /**
35  * SECTION:generic_values
36  * @short_description: A polymorphic type that can hold values of any
37  *     other type
38  * @see_also: The fundamental types which all support #GValue
39  *     operations and thus can be used as a type initializer for
40  *     g_value_init() are defined by a separate interface.  See the <link
41  *     linkend="gobject-Standard-Parameter-and-Value-Types">Standard
42  *     Values API</link> for details.
43  * @title: Generic values
44  *
45  * The #GValue structure is basically a variable container that consists
46  * of a type identifier and a specific value of that type.
47  * The type identifier within a #GValue structure always determines the
48  * type of the associated value.
49  * To create a undefined #GValue structure, simply create a zero-filled
50  * #GValue structure. To initialize the #GValue, use the g_value_init()
51  * function. A #GValue cannot be used until it is initialized.
52  * The basic type operations (such as freeing and copying) are determined
53  * by the #GTypeValueTable associated with the type ID stored in the #GValue.
54  * Other #GValue operations (such as converting values between types) are
55  * provided by this interface.
56  *
57  * The code in the example program below demonstrates #GValue's
58  * features.
59  *
60  * |[
61  * #include &lt;glib-object.h&gt;
62  *
63  * static void
64  * int2string (const GValue *src_value,
65  *             GValue       *dest_value)
66  * {
67  *   if (g_value_get_int (src_value) == 42)
68  *     g_value_set_static_string (dest_value, "An important number");
69  *   else
70  *     g_value_set_static_string (dest_value, "What's that?");
71  * }
72  *
73  * int
74  * main (int   argc,
75  *       char *argv[])
76  * {
77  *   /&ast; GValues must be initialized &ast;/
78  *   GValue a = G_VALUE_INIT;
79  *   GValue b = G_VALUE_INIT;
80  *   const gchar *message;
81  *
82  *   g_type_init ();
83  *
84  *   /&ast; The GValue starts empty &ast;/
85  *   g_assert (!G_VALUE_HOLDS_STRING (&amp;a));
86  *
87  *   /&ast; Put a string in it &ast;/
88  *   g_value_init (&amp;a, G_TYPE_STRING);
89  *   g_assert (G_VALUE_HOLDS_STRING (&amp;a));
90  *   g_value_set_static_string (&amp;a, "Hello, world!");
91  *   g_printf ("%s\n", g_value_get_string (&amp;a));
92  *
93  *   /&ast; Reset it to its pristine state &ast;/
94  *   g_value_unset (&amp;a);
95  *
96  *   /&ast; It can then be reused for another type &ast;/
97  *   g_value_init (&amp;a, G_TYPE_INT);
98  *   g_value_set_int (&amp;a, 42);
99  *
100  *   /&ast; Attempt to transform it into a GValue of type STRING &ast;/
101  *   g_value_init (&amp;b, G_TYPE_STRING);
102  *
103  *   /&ast; An INT is transformable to a STRING &ast;/
104  *   g_assert (g_value_type_transformable (G_TYPE_INT, G_TYPE_STRING));
105  *
106  *   g_value_transform (&amp;a, &amp;b);
107  *   g_printf ("%s\n", g_value_get_string (&amp;b));
108  *
109  *   /&ast; Attempt to transform it again using a custom transform function &ast;/
110  *   g_value_register_transform_func (G_TYPE_INT, G_TYPE_STRING, int2string);
111  *   g_value_transform (&amp;a, &amp;b);
112  *   g_printf ("%s\n", g_value_get_string (&amp;b));
113  *   return 0;
114  * }
115  * ]|
116  */
117
118
119 /* --- typedefs & structures --- */
120 typedef struct {
121   GType src_type;
122   GType dest_type;
123   GValueTransform func;
124 } TransformEntry;
125
126
127 /* --- prototypes --- */
128 static gint     transform_entries_cmp   (gconstpointer bsearch_node1,
129                                          gconstpointer bsearch_node2);
130
131
132 /* --- variables --- */
133 static GBSearchArray *transform_array = NULL;
134 static GBSearchConfig transform_bconfig = {
135   sizeof (TransformEntry),
136   transform_entries_cmp,
137   G_BSEARCH_ARRAY_ALIGN_POWER2,
138 };
139
140
141 /* --- functions --- */
142 void
143 _g_value_c_init (void)
144 {
145   transform_array = g_bsearch_array_create (&transform_bconfig);
146 }
147
148 static inline void              /* keep this function in sync with gvaluecollector.h and gboxed.c */
149 value_meminit (GValue *value,
150                GType   value_type)
151 {
152   value->g_type = value_type;
153   memset (value->data, 0, sizeof (value->data));
154 }
155
156 /**
157  * g_value_init:
158  * @value: A zero-filled (uninitialized) #GValue structure.
159  * @g_type: Type the #GValue should hold values of.
160  *
161  * Initializes @value with the default value of @type.
162  *
163  * Returns: (transfer none): the #GValue structure that has been passed in
164  */
165 GValue*
166 g_value_init (GValue *value,
167               GType   g_type)
168 {
169   /* g_return_val_if_fail (G_TYPE_IS_VALUE (g_type), NULL);     be more elaborate below */
170   g_return_val_if_fail (value != NULL, NULL);
171   /* g_return_val_if_fail (G_VALUE_TYPE (value) == 0, NULL);    be more elaborate below */
172
173   if (G_TYPE_IS_VALUE (g_type) && G_VALUE_TYPE (value) == 0)
174     {
175       GTypeValueTable *value_table = g_type_value_table_peek (g_type);
176
177       /* setup and init */
178       value_meminit (value, g_type);
179       value_table->value_init (value);
180     }
181   else if (G_VALUE_TYPE (value))
182     g_warning ("%s: cannot initialize GValue with type `%s', the value has already been initialized as `%s'",
183                G_STRLOC,
184                g_type_name (g_type),
185                g_type_name (G_VALUE_TYPE (value)));
186   else /* !G_TYPE_IS_VALUE (g_type) */
187     g_warning ("%s: cannot initialize GValue with type `%s', %s",
188                G_STRLOC,
189                g_type_name (g_type),
190                g_type_value_table_peek (g_type) ?
191                "this type is abstract with regards to GValue use, use a more specific (derived) type" :
192                "this type has no GTypeValueTable implementation");
193   return value;
194 }
195
196 /**
197  * g_value_copy:
198  * @src_value: An initialized #GValue structure.
199  * @dest_value: An initialized #GValue structure of the same type as @src_value.
200  *
201  * Copies the value of @src_value into @dest_value.
202  */
203 void
204 g_value_copy (const GValue *src_value,
205               GValue       *dest_value)
206 {
207   g_return_if_fail (G_IS_VALUE (src_value));
208   g_return_if_fail (G_IS_VALUE (dest_value));
209   g_return_if_fail (g_value_type_compatible (G_VALUE_TYPE (src_value), G_VALUE_TYPE (dest_value)));
210   
211   if (src_value != dest_value)
212     {
213       GType dest_type = G_VALUE_TYPE (dest_value);
214       GTypeValueTable *value_table = g_type_value_table_peek (dest_type);
215
216       /* make sure dest_value's value is free()d */
217       if (value_table->value_free)
218         value_table->value_free (dest_value);
219
220       /* setup and copy */
221       value_meminit (dest_value, dest_type);
222       value_table->value_copy (src_value, dest_value);
223     }
224 }
225
226 /**
227  * g_value_reset:
228  * @value: An initialized #GValue structure.
229  *
230  * Clears the current value in @value and resets it to the default value
231  * (as if the value had just been initialized).
232  *
233  * Returns: the #GValue structure that has been passed in
234  */
235 GValue*
236 g_value_reset (GValue *value)
237 {
238   GTypeValueTable *value_table;
239   GType g_type;
240   
241   g_return_val_if_fail (G_IS_VALUE (value), NULL);
242   
243   g_type = G_VALUE_TYPE (value);
244   value_table = g_type_value_table_peek (g_type);
245
246   /* make sure value's value is free()d */
247   if (value_table->value_free)
248     value_table->value_free (value);
249
250   /* setup and init */
251   value_meminit (value, g_type);
252   value_table->value_init (value);
253
254   return value;
255 }
256
257 /**
258  * g_value_unset:
259  * @value: An initialized #GValue structure.
260  *
261  * Clears the current value in @value and "unsets" the type,
262  * this releases all resources associated with this GValue.
263  * An unset value is the same as an uninitialized (zero-filled)
264  * #GValue structure.
265  */
266 void
267 g_value_unset (GValue *value)
268 {
269   GTypeValueTable *value_table;
270   
271   g_return_if_fail (G_IS_VALUE (value));
272
273   value_table = g_type_value_table_peek (G_VALUE_TYPE (value));
274
275   if (value_table->value_free)
276     value_table->value_free (value);
277   memset (value, 0, sizeof (*value));
278 }
279
280 /**
281  * g_value_fits_pointer:
282  * @value: An initialized #GValue structure.
283  *
284  * Determines if @value will fit inside the size of a pointer value.
285  * This is an internal function introduced mainly for C marshallers.
286  *
287  * Returns: %TRUE if @value will fit inside a pointer value.
288  */
289 gboolean
290 g_value_fits_pointer (const GValue *value)
291 {
292   GTypeValueTable *value_table;
293
294   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
295
296   value_table = g_type_value_table_peek (G_VALUE_TYPE (value));
297
298   return value_table->value_peek_pointer != NULL;
299 }
300
301 /**
302  * g_value_peek_pointer:
303  * @value: An initialized #GValue structure.
304  *
305  * Returns: (transfer none): the value contents as pointer. This
306  * function asserts that g_value_fits_pointer() returned %TRUE for the
307  * passed in value.  This is an internal function introduced mainly
308  * for C marshallers.
309  */
310 gpointer
311 g_value_peek_pointer (const GValue *value)
312 {
313   GTypeValueTable *value_table;
314
315   g_return_val_if_fail (G_IS_VALUE (value), NULL);
316
317   value_table = g_type_value_table_peek (G_VALUE_TYPE (value));
318   if (!value_table->value_peek_pointer)
319     {
320       g_return_val_if_fail (g_value_fits_pointer (value) == TRUE, NULL);
321       return NULL;
322     }
323
324   return value_table->value_peek_pointer (value);
325 }
326
327 /**
328  * g_value_set_instance:
329  * @value: An initialized #GValue structure.
330  * @instance: (allow-none): the instance
331  *
332  * Sets @value from an instantiatable type via the
333  * value_table's collect_value() function.
334  */
335 void
336 g_value_set_instance (GValue  *value,
337                       gpointer instance)
338 {
339   GType g_type;
340   GTypeValueTable *value_table;
341   GTypeCValue cvalue;
342   gchar *error_msg;
343   
344   g_return_if_fail (G_IS_VALUE (value));
345   if (instance)
346     {
347       g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
348       g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (instance), G_VALUE_TYPE (value)));
349     }
350   
351   g_type = G_VALUE_TYPE (value);
352   value_table = g_type_value_table_peek (g_type);
353   
354   g_return_if_fail (strcmp (value_table->collect_format, "p") == 0);
355   
356   memset (&cvalue, 0, sizeof (cvalue));
357   cvalue.v_pointer = instance;
358   
359   /* make sure value's value is free()d */
360   if (value_table->value_free)
361     value_table->value_free (value);
362
363   /* setup and collect */
364   value_meminit (value, g_type);
365   error_msg = value_table->collect_value (value, 1, &cvalue, 0);
366   if (error_msg)
367     {
368       g_warning ("%s: %s", G_STRLOC, error_msg);
369       g_free (error_msg);
370       
371       /* we purposely leak the value here, it might not be
372        * in a sane state if an error condition occoured
373        */
374       value_meminit (value, g_type);
375       value_table->value_init (value);
376     }
377 }
378
379 static GValueTransform
380 transform_func_lookup (GType src_type,
381                        GType dest_type)
382 {
383   TransformEntry entry;
384
385   entry.src_type = src_type;
386   do
387     {
388       entry.dest_type = dest_type;
389       do
390         {
391           TransformEntry *e;
392           
393           e = g_bsearch_array_lookup (transform_array, &transform_bconfig, &entry);
394           if (e)
395             {
396               /* need to check that there hasn't been a change in value handling */
397               if (g_type_value_table_peek (entry.dest_type) == g_type_value_table_peek (dest_type) &&
398                   g_type_value_table_peek (entry.src_type) == g_type_value_table_peek (src_type))
399                 return e->func;
400             }
401           entry.dest_type = g_type_parent (entry.dest_type);
402         }
403       while (entry.dest_type);
404       
405       entry.src_type = g_type_parent (entry.src_type);
406     }
407   while (entry.src_type);
408
409   return NULL;
410 }
411
412 static gint
413 transform_entries_cmp (gconstpointer bsearch_node1,
414                        gconstpointer bsearch_node2)
415 {
416   const TransformEntry *e1 = bsearch_node1;
417   const TransformEntry *e2 = bsearch_node2;
418   gint cmp = G_BSEARCH_ARRAY_CMP (e1->src_type, e2->src_type);
419
420   if (cmp)
421     return cmp;
422   else
423     return G_BSEARCH_ARRAY_CMP (e1->dest_type, e2->dest_type);
424 }
425
426 /**
427  * g_value_register_transform_func: (skip)
428  * @src_type: Source type.
429  * @dest_type: Target type.
430  * @transform_func: a function which transforms values of type @src_type
431  *  into value of type @dest_type
432  *
433  * Registers a value transformation function for use in g_value_transform().
434  * A previously registered transformation function for @src_type and @dest_type
435  * will be replaced.
436  */
437 void
438 g_value_register_transform_func (GType           src_type,
439                                  GType           dest_type,
440                                  GValueTransform transform_func)
441 {
442   TransformEntry entry;
443
444   /* these checks won't pass for dynamic types.
445    * g_return_if_fail (G_TYPE_HAS_VALUE_TABLE (src_type));
446    * g_return_if_fail (G_TYPE_HAS_VALUE_TABLE (dest_type));
447    */
448   g_return_if_fail (transform_func != NULL);
449
450   entry.src_type = src_type;
451   entry.dest_type = dest_type;
452
453 #if 0 /* let transform function replacement be a valid operation */
454   if (g_bsearch_array_lookup (transform_array, &transform_bconfig, &entry))
455     g_warning ("reregistering value transformation function (%p) for `%s' to `%s'",
456                transform_func,
457                g_type_name (src_type),
458                g_type_name (dest_type));
459 #endif
460
461   entry.func = transform_func;
462   transform_array = g_bsearch_array_replace (transform_array, &transform_bconfig, &entry);
463 }
464
465 /**
466  * g_value_type_transformable:
467  * @src_type: Source type.
468  * @dest_type: Target type.
469  *
470  * Check whether g_value_transform() is able to transform values
471  * of type @src_type into values of type @dest_type.
472  *
473  * Returns: %TRUE if the transformation is possible, %FALSE otherwise.
474  */
475 gboolean
476 g_value_type_transformable (GType src_type,
477                             GType dest_type)
478 {
479   g_return_val_if_fail (G_TYPE_IS_VALUE (src_type), FALSE);
480   g_return_val_if_fail (G_TYPE_IS_VALUE (dest_type), FALSE);
481
482   return (g_value_type_compatible (src_type, dest_type) ||
483           transform_func_lookup (src_type, dest_type) != NULL);
484 }
485
486 /**
487  * g_value_type_compatible:
488  * @src_type: source type to be copied.
489  * @dest_type: destination type for copying.
490  *
491  * Returns whether a #GValue of type @src_type can be copied into
492  * a #GValue of type @dest_type.
493  *
494  * Returns: %TRUE if g_value_copy() is possible with @src_type and @dest_type.
495  */
496 gboolean
497 g_value_type_compatible (GType src_type,
498                          GType dest_type)
499 {
500   g_return_val_if_fail (G_TYPE_IS_VALUE (src_type), FALSE);
501   g_return_val_if_fail (G_TYPE_IS_VALUE (dest_type), FALSE);
502
503   return (g_type_is_a (src_type, dest_type) &&
504           g_type_value_table_peek (dest_type) == g_type_value_table_peek (src_type));
505 }
506
507 /**
508  * g_value_transform:
509  * @src_value: Source value.
510  * @dest_value: Target value.
511  *
512  * Tries to cast the contents of @src_value into a type appropriate
513  * to store in @dest_value, e.g. to transform a %G_TYPE_INT value
514  * into a %G_TYPE_FLOAT value. Performing transformations between
515  * value types might incur precision lossage. Especially
516  * transformations into strings might reveal seemingly arbitrary
517  * results and shouldn't be relied upon for production code (such
518  * as rcfile value or object property serialization).
519  *
520  * Returns: Whether a transformation rule was found and could be applied.
521  *  Upon failing transformations, @dest_value is left untouched.
522  */
523 gboolean
524 g_value_transform (const GValue *src_value,
525                    GValue       *dest_value)
526 {
527   GType dest_type;
528
529   g_return_val_if_fail (G_IS_VALUE (src_value), FALSE);
530   g_return_val_if_fail (G_IS_VALUE (dest_value), FALSE);
531
532   dest_type = G_VALUE_TYPE (dest_value);
533   if (g_value_type_compatible (G_VALUE_TYPE (src_value), dest_type))
534     {
535       g_value_copy (src_value, dest_value);
536       
537       return TRUE;
538     }
539   else
540     {
541       GValueTransform transform = transform_func_lookup (G_VALUE_TYPE (src_value), dest_type);
542
543       if (transform)
544         {
545           g_value_unset (dest_value);
546           
547           /* setup and transform */
548           value_meminit (dest_value, dest_type);
549           transform (src_value, dest_value);
550           
551           return TRUE;
552         }
553     }
554   return FALSE;
555 }