define gstring in terms of gchar*. this typedef reflects the type name of
[platform/upstream/glib.git] / gobject / gvalue.c
1 /* GObject - GLib Type, Object, Parameter and Signal Library
2  * Copyright (C) 1997, 1998, 1999, 2000 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 #include        "gvalue.h"
20
21
22 /* --- typedefs & structures --- */
23 typedef struct
24 {
25   GType          value_type1;
26   GType          value_type2;
27   GValueExchange func;
28   GType          first_type;
29 } ExchangeEntry;
30
31
32 /* --- variables --- */
33 static GHashTable *param_exchange_ht = NULL;
34
35
36 /* --- functions --- */
37 void
38 g_value_init (GValue *value,
39               GType   g_type)
40 {
41   GTypeValueTable *value_table = g_type_value_table_peek (g_type);
42   
43   g_return_if_fail (value != NULL);
44   g_return_if_fail (G_VALUE_TYPE (value) == 0);
45   
46   if (value_table)
47     {
48       memset (value, 0, sizeof (*value));
49       value->g_type = g_type;
50       value_table->value_init (value);
51     }
52   else
53     g_warning (G_STRLOC ": cannot initialize value of type `%s' which has no GTypeValueTable",
54                g_type_name (g_type));
55 }
56
57 void
58 g_value_copy (const GValue *src_value,
59               GValue       *dest_value)
60 {
61   GTypeValueTable *value_table = g_type_value_table_peek (G_VALUE_TYPE (dest_value));
62   
63   g_return_if_fail (G_IS_VALUE (src_value));
64   g_return_if_fail (G_IS_VALUE (dest_value));
65   g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), G_VALUE_TYPE (dest_value)));
66   if (!value_table)
67     g_return_if_fail (g_type_value_table_peek (G_VALUE_TYPE (dest_value)) != NULL);
68   
69   if (src_value != dest_value)
70     {
71       /* make sure dest_value's value is free()d and zero initialized */
72       g_value_reset (dest_value);
73       
74       value_table->value_copy (src_value, dest_value);
75     }
76 }
77
78 void
79 g_value_unset (GValue *value)
80 {
81   GTypeValueTable *value_table = g_type_value_table_peek (G_VALUE_TYPE (value));
82   
83   g_return_if_fail (G_IS_VALUE (value));
84   if (!value_table)
85     g_return_if_fail (g_type_value_table_peek (G_VALUE_TYPE (value)) != NULL);
86   
87   if (value_table->value_free)
88     value_table->value_free (value);
89   memset (value, 0, sizeof (*value));
90 }
91
92 void
93 g_value_reset (GValue *value)
94 {
95   GTypeValueTable *value_table = g_type_value_table_peek (G_VALUE_TYPE (value));
96   GType g_type;
97   
98   g_return_if_fail (G_IS_VALUE (value));
99   
100   g_type = G_VALUE_TYPE (value);
101   
102   if (value_table->value_free)
103     value_table->value_free (value);
104   memset (value, 0, sizeof (*value));
105   
106   value->g_type = g_type;
107   value_table->value_init (value);
108 }
109
110 static gint
111 exchange_entries_equal (gconstpointer v1,
112                         gconstpointer v2)
113 {
114   const ExchangeEntry *entry1 = v1;
115   const ExchangeEntry *entry2 = v2;
116   
117   return (entry1->value_type1 == entry2->value_type1 &&
118           entry1->value_type2 == entry2->value_type2);
119 }
120
121 static guint
122 exchange_entry_hash (gconstpointer key)
123 {
124   const ExchangeEntry *entry = key;
125   
126   return entry->value_type1 ^ entry->value_type2;
127 }
128
129 static void
130 value_exchange_memcpy (GValue *value1,
131                        GValue *value2)
132 {
133   GValue tmp_value;
134   
135   memcpy (&tmp_value.data, &value1->data, sizeof (value1->data));
136   memcpy (&value1->data, &value2->data, sizeof (value1->data));
137   memcpy (&value2->data, &tmp_value.data, sizeof (value2->data));
138 }
139
140 static inline GValueExchange
141 exchange_func_lookup (GType     value_type1,
142                       GType     value_type2,
143                       gboolean *need_swap)
144 {
145   if (value_type1 == value_type2)
146     return value_exchange_memcpy;
147   else
148     {
149       GType type1 = value_type1;
150       
151       do
152         {
153           GType type2 = value_type2;
154           
155           do
156             {
157               ExchangeEntry entry, *ret;
158               
159               entry.value_type1 = MIN (type1, type2);
160               entry.value_type2 = MAX (type1, type2);
161               ret = g_hash_table_lookup (param_exchange_ht, &entry);
162               if (ret)
163                 {
164                   if (need_swap)
165                     *need_swap = ret->first_type == type2;
166                   
167                   return ret->func;
168                 }
169               
170               type2 = g_type_parent (type2);
171             }
172           while (type2);
173           
174           type1 = g_type_parent (type1);
175         }
176       while (type1);
177     }
178   
179   return NULL;
180 }
181
182 void
183 g_value_register_exchange_func (GType          value_type1,
184                                 GType          value_type2,
185                                 GValueExchange func)
186 {
187   ExchangeEntry entry;
188   
189   g_return_if_fail (G_TYPE_IS_VALUE (value_type1));
190   g_return_if_fail (G_TYPE_IS_VALUE (value_type2));
191   g_return_if_fail (func != NULL);
192   
193   entry.value_type1 = MIN (value_type1, value_type2);
194   entry.value_type2 = MAX (value_type1, value_type2);
195   if (param_exchange_ht && g_hash_table_lookup (param_exchange_ht, &entry))
196     g_warning (G_STRLOC ": cannot re-register param value exchange function "
197                "for `%s' and `%s'",
198                g_type_name (value_type1),
199                g_type_name (value_type2));
200   else
201     {
202       ExchangeEntry *entry = g_new (ExchangeEntry, 1);
203       
204       if (!param_exchange_ht)
205         param_exchange_ht = g_hash_table_new (exchange_entry_hash, exchange_entries_equal);
206       entry->value_type1 = MIN (value_type1, value_type2);
207       entry->value_type2 = MAX (value_type1, value_type2);
208       entry->func = func;
209       entry->first_type = value_type1;
210       g_hash_table_insert (param_exchange_ht, entry, entry);
211     }
212 }
213
214 gboolean
215 g_value_types_exchangable (GType value_type1,
216                            GType value_type2)
217 {
218   g_return_val_if_fail (G_TYPE_IS_VALUE (value_type1), FALSE);
219   g_return_val_if_fail (G_TYPE_IS_VALUE (value_type2), FALSE);
220   
221   return exchange_func_lookup (value_type1, value_type2, NULL) != NULL;
222 }
223
224 gboolean
225 g_values_exchange (GValue *value1,
226                    GValue *value2)
227 {
228   g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
229   g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
230   
231   if (value1 != value2)
232     {
233       gboolean need_swap;
234       GValueExchange value_exchange = exchange_func_lookup (G_VALUE_TYPE (value1),
235                                                             G_VALUE_TYPE (value2),
236                                                             &need_swap);
237       if (value_exchange)
238         {
239           if (need_swap)
240             value_exchange (value2, value1);
241           else
242             value_exchange (value1, value2);
243         }
244       
245       return value_exchange != NULL;
246     }
247   
248   return TRUE;
249 }
250
251 gboolean
252 g_value_convert (const GValue *src_value,
253                  GValue       *dest_value)
254 {
255   gboolean success = TRUE;
256   
257   g_return_val_if_fail (G_IS_VALUE (src_value), FALSE);
258   g_return_val_if_fail (G_IS_VALUE (dest_value), FALSE);
259   
260   if (src_value != dest_value)
261     {
262       GValue tmp_value = { 0, };
263       
264       g_value_init (&tmp_value, G_VALUE_TYPE (src_value));
265       g_value_copy (src_value, &tmp_value);
266       
267       success = g_values_exchange (&tmp_value, dest_value);
268       g_value_unset (&tmp_value);
269     }
270   
271   return success;
272 }