gobject/: fully remove gobjectalias hacks
[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 start zero-filled &ast;/
77  *   GValue a = {0};
78  *   GValue b = {0};
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: 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  * Return the value contents as pointer. This function asserts that
305  * g_value_fits_pointer() returned %TRUE for the passed in value.
306  * This is an internal function introduced mainly for C marshallers.
307  *
308  * Returns: %TRUE if @value will fit inside a pointer value.
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: 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:
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 }