1 /* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 1997, 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
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.
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.
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.
23 #define G_PARAM_SPEC_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_PARAM, GParamSpecClass))
26 /* --- typedefs & structures --- */
36 /* --- variables --- */
37 static GHashTable *param_exchange_ht = NULL;
40 /* --- functions --- */
42 g_value_init (GValue *value,
45 GParamSpecClass *pclass;
47 g_return_if_fail (value != NULL);
48 g_return_if_fail (G_VALUE_TYPE (value) == 0);
49 g_type = g_type_next_base (g_type, G_TYPE_PARAM);
50 g_return_if_fail (G_TYPE_IS_VALUE (g_type));
52 memset (value, 0, sizeof (*value));
53 value->g_type = g_type;
55 pclass = g_type_class_ref (G_VALUE_TYPE (value));
56 pclass->param_init (value, NULL);
57 g_type_class_unref (pclass);
61 g_value_init_default (GValue *value,
64 g_return_if_fail (value != NULL);
65 g_return_if_fail (G_VALUE_TYPE (value) == 0);
66 g_return_if_fail (G_IS_PARAM_SPEC (pspec));
68 memset (value, 0, sizeof (*value));
69 value->g_type = g_type_next_base (G_PARAM_SPEC_TYPE (pspec), G_TYPE_PARAM);
71 G_PARAM_SPEC_GET_CLASS (pspec)->param_init (value, pspec);
75 g_value_validate (GValue *value,
78 g_return_val_if_fail (G_IS_VALUE (value), FALSE);
79 g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
80 g_return_val_if_fail (g_type_is_a (G_PARAM_SPEC_TYPE (pspec), G_VALUE_TYPE (value)), FALSE);
82 if (G_PARAM_SPEC_GET_CLASS (pspec)->param_validate)
86 if (G_PARAM_SPEC_GET_CLASS (pspec)->param_validate (value, pspec) ||
87 memcmp (&oval.data, &value->data, sizeof (oval.data)))
94 g_value_defaults (const GValue *value,
97 GValue dflt_value = { 0, };
100 g_return_val_if_fail (G_IS_VALUE (value), FALSE);
101 g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
102 g_return_val_if_fail (g_type_is_a (G_PARAM_SPEC_TYPE (pspec), G_VALUE_TYPE (value)), FALSE);
104 dflt_value.g_type = g_type_next_base (G_PARAM_SPEC_TYPE (pspec), G_TYPE_PARAM);
105 G_PARAM_SPEC_GET_CLASS (pspec)->param_init (&dflt_value, pspec);
106 defaults = g_values_cmp (value, &dflt_value, pspec) == 0;
107 g_value_unset (&dflt_value);
113 g_value_set_default (GValue *value,
116 GValue tmp_value = { 0, };
118 g_return_if_fail (G_IS_VALUE (value));
119 g_return_if_fail (G_IS_PARAM_SPEC (pspec));
120 g_return_if_fail (g_type_is_a (G_PARAM_SPEC_TYPE (pspec), G_VALUE_TYPE (value)));
122 /* retrive default value */
123 tmp_value.g_type = g_type_next_base (G_PARAM_SPEC_TYPE (pspec), G_TYPE_PARAM);
124 G_PARAM_SPEC_GET_CLASS (pspec)->param_init (&tmp_value, pspec);
126 /* set default value */
127 g_values_exchange (&tmp_value, value);
129 g_value_unset (&tmp_value);
133 g_values_cmp (const GValue *value1,
134 const GValue *value2,
137 GParamSpecClass *pclass;
140 /* param_values_cmp() effectively does: value1 - value2
141 * so the return values are:
142 * -1) value1 < value2
143 * 0) value1 == value2
146 g_return_val_if_fail (G_IS_VALUE (value1), 0);
147 g_return_val_if_fail (G_IS_VALUE (value2), 0);
148 g_return_val_if_fail (G_VALUE_TYPE (value1) == G_VALUE_TYPE (value2), 0);
151 g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), 0);
152 g_return_val_if_fail (g_type_is_a (G_PARAM_SPEC_TYPE (pspec), G_VALUE_TYPE (value1)), FALSE);
155 pclass = g_type_class_ref (G_VALUE_TYPE (value1));
156 cmp = pclass->param_values_cmp (value1, value2, pspec);
157 g_type_class_unref (pclass);
159 return CLAMP (cmp, -1, 1);
163 g_value_copy (const GValue *src_value,
166 g_return_if_fail (G_IS_VALUE (src_value));
167 g_return_if_fail (G_IS_VALUE (dest_value));
168 g_return_if_fail (G_VALUE_TYPE (src_value) == G_VALUE_TYPE (dest_value));
170 if (src_value != dest_value)
172 GParamSpecClass *pclass = g_type_class_ref (G_VALUE_TYPE (src_value));
174 /* make sure dest_value's value is free()d and zero initialized */
175 g_value_reset (dest_value);
177 if (pclass->param_copy_value)
178 pclass->param_copy_value (src_value, dest_value);
180 memcpy (&dest_value->data, &src_value->data, sizeof (src_value->data));
181 g_type_class_unref (pclass);
186 g_value_unset (GValue *value)
188 GParamSpecClass *pclass;
190 g_return_if_fail (G_IS_VALUE (value));
192 pclass = g_type_class_ref (G_VALUE_TYPE (value));
193 if (pclass->param_free_value)
194 pclass->param_free_value (value);
195 memset (value, 0, sizeof (*value));
196 g_type_class_unref (pclass);
200 g_value_reset (GValue *value)
202 GParamSpecClass *pclass;
205 g_return_if_fail (G_IS_VALUE (value));
207 g_type = G_VALUE_TYPE (value);
208 pclass = g_type_class_ref (g_type);
210 if (pclass->param_free_value)
211 pclass->param_free_value (value);
212 memset (value, 0, sizeof (*value));
214 value->g_type = g_type;
215 pclass->param_init (value, NULL);
217 g_type_class_unref (pclass);
221 exchange_entries_equal (gconstpointer v1,
224 const ExchangeEntry *entry1 = v1;
225 const ExchangeEntry *entry2 = v2;
227 return (entry1->value_type1 == entry2->value_type1 &&
228 entry1->value_type2 == entry2->value_type2);
232 exchange_entry_hash (gconstpointer key)
234 const ExchangeEntry *entry = key;
236 return entry->value_type1 ^ entry->value_type2;
240 value_exchange_memcpy (GValue *value1,
245 memcpy (&tmp_value.data, &value1->data, sizeof (value1->data));
246 memcpy (&value1->data, &value2->data, sizeof (value1->data));
247 memcpy (&value2->data, &tmp_value.data, sizeof (value2->data));
250 static inline GValueExchange
251 exchange_func_lookup (GType value_type1,
255 if (value_type1 == value_type2)
256 return value_exchange_memcpy;
259 ExchangeEntry entry, *ret;
261 entry.value_type1 = MIN (value_type1, value_type2);
262 entry.value_type2 = MAX (value_type1, value_type2);
264 ret = g_hash_table_lookup (param_exchange_ht, &entry);
268 *need_swap = ret->first_type == value_type1;
277 g_value_register_exchange_func (GType value_type1,
283 g_return_if_fail (G_TYPE_IS_VALUE (value_type1));
284 g_return_if_fail (G_TYPE_IS_VALUE (value_type2));
285 g_return_if_fail (func != NULL);
287 type1 = g_type_next_base (value_type1, G_TYPE_PARAM);
288 type2 = g_type_next_base (value_type2, G_TYPE_PARAM);
290 if (param_exchange_ht && exchange_func_lookup (type1, type2, NULL))
291 g_warning (G_STRLOC ": cannot re-register param value exchange function "
294 g_type_name (type2));
297 ExchangeEntry *entry = g_new (ExchangeEntry, 1);
299 if (!param_exchange_ht)
300 param_exchange_ht = g_hash_table_new (exchange_entry_hash, exchange_entries_equal);
301 entry->value_type1 = MIN (type1, type2);
302 entry->value_type2 = MAX (type1, type2);
304 entry->first_type = type1;
305 g_hash_table_insert (param_exchange_ht, entry, entry);
310 g_value_types_exchangable (GType value_type1,
315 g_return_val_if_fail (G_TYPE_IS_VALUE (value_type1), FALSE);
316 g_return_val_if_fail (G_TYPE_IS_VALUE (value_type2), FALSE);
318 type1 = g_type_next_base (value_type1, G_TYPE_PARAM);
319 type2 = g_type_next_base (value_type2, G_TYPE_PARAM);
321 return exchange_func_lookup (type1, type2, NULL) != NULL;
325 g_values_exchange (GValue *value1,
328 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
329 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
331 if (value1 != value2)
333 GType type1 = g_type_next_base (G_VALUE_TYPE (value1), G_TYPE_PARAM);
334 GType type2 = g_type_next_base (G_VALUE_TYPE (value2), G_TYPE_PARAM);
336 GValueExchange value_exchange = exchange_func_lookup (type1,
342 value_exchange (value2, value1);
344 value_exchange (value1, value2);
347 return value_exchange != NULL;
354 g_value_convert (const GValue *src_value,
357 gboolean success = TRUE;
359 g_return_val_if_fail (G_IS_VALUE (src_value), FALSE);
360 g_return_val_if_fail (G_IS_VALUE (dest_value), FALSE);
362 if (src_value != dest_value)
364 GValue tmp_value = { 0, };
366 g_value_init (&tmp_value, G_VALUE_TYPE (src_value));
367 g_value_copy (src_value, &tmp_value);
369 success = g_values_exchange (&tmp_value, dest_value);
370 g_value_unset (&tmp_value);