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