1 /* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 1997-1999, 2000-2001 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.
27 #include "gvaluecollector.h"
28 #include "gbsearcharray.h"
31 /* --- typedefs & structures --- */
39 /* --- prototypes --- */
40 static gint
transform_entries_cmp (gconstpointer bsearch_node1
,
41 gconstpointer bsearch_node2
);
44 /* --- variables --- */
45 static GBSearchArray transform_array
= G_STATIC_BSEARCH_ARRAY_INIT (sizeof (TransformEntry
),
46 transform_entries_cmp
,
50 /* --- functions --- */
51 static inline void /* keep this function in sync with gvaluecollector.h and gboxed.c */
52 value_meminit (GValue
*value
,
55 value
->g_type
= value_type
;
56 memset (value
->data
, 0, sizeof (value
->data
));
60 g_value_init (GValue
*value
,
63 /* g_return_val_if_fail (G_TYPE_IS_VALUE (g_type), NULL); be more elaborate below */
64 g_return_val_if_fail (value
!= NULL
, NULL
);
65 /* g_return_val_if_fail (G_VALUE_TYPE (value) == 0, NULL); be more elaborate below */
67 if (G_TYPE_IS_VALUE (g_type
) && G_VALUE_TYPE (value
) == 0)
69 GTypeValueTable
*value_table
= g_type_value_table_peek (g_type
);
72 value_meminit (value
, g_type
);
73 value_table
->value_init (value
);
75 else if (G_VALUE_TYPE (value
))
76 g_warning ("%s: cannot initialize GValue with type `%s', the value has already been initialized as `%s'",
79 g_type_name (G_VALUE_TYPE (value
)));
80 else /* !G_TYPE_IS_VALUE (g_type) */
81 g_warning ("%s: cannot initialize GValue with type `%s', %s",
84 g_type_value_table_peek (g_type
) ?
85 "this type is abstract with regards to GValue use, use a more specific (derived) type" :
86 "this type has no GTypeValueTable implementation");
91 g_value_copy (const GValue
*src_value
,
94 g_return_if_fail (G_IS_VALUE (src_value
));
95 g_return_if_fail (G_IS_VALUE (dest_value
));
96 g_return_if_fail (g_value_type_compatible (G_VALUE_TYPE (src_value
), G_VALUE_TYPE (dest_value
)));
98 if (src_value
!= dest_value
)
100 GType dest_type
= G_VALUE_TYPE (dest_value
);
101 GTypeValueTable
*value_table
= g_type_value_table_peek (dest_type
);
103 /* make sure dest_value's value is free()d */
104 if (value_table
->value_free
)
105 value_table
->value_free (dest_value
);
108 value_meminit (dest_value
, dest_type
);
109 value_table
->value_copy (src_value
, dest_value
);
114 g_value_reset (GValue
*value
)
116 GTypeValueTable
*value_table
;
119 g_return_val_if_fail (G_IS_VALUE (value
), NULL
);
121 g_type
= G_VALUE_TYPE (value
);
122 value_table
= g_type_value_table_peek (g_type
);
124 /* make sure value's value is free()d */
125 if (value_table
->value_free
)
126 value_table
->value_free (value
);
129 value_meminit (value
, g_type
);
130 value_table
->value_init (value
);
136 g_value_unset (GValue
*value
)
138 GTypeValueTable
*value_table
;
140 g_return_if_fail (G_IS_VALUE (value
));
142 value_table
= g_type_value_table_peek (G_VALUE_TYPE (value
));
144 if (value_table
->value_free
)
145 value_table
->value_free (value
);
146 memset (value
, 0, sizeof (*value
));
150 g_value_fits_pointer (const GValue
*value
)
152 GTypeValueTable
*value_table
;
154 g_return_val_if_fail (G_IS_VALUE (value
), FALSE
);
156 value_table
= g_type_value_table_peek (G_VALUE_TYPE (value
));
158 return value_table
->value_peek_pointer
!= NULL
;
162 g_value_peek_pointer (const GValue
*value
)
164 GTypeValueTable
*value_table
;
166 g_return_val_if_fail (G_IS_VALUE (value
), NULL
);
168 value_table
= g_type_value_table_peek (G_VALUE_TYPE (value
));
169 if (!value_table
->value_peek_pointer
)
170 g_return_val_if_fail (g_value_fits_pointer (value
) == TRUE
, NULL
);
172 return value_table
->value_peek_pointer (value
);
176 g_value_set_instance (GValue
*value
,
180 GTypeValueTable
*value_table
;
184 g_return_if_fail (G_IS_VALUE (value
));
187 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance
));
188 g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (instance
), G_VALUE_TYPE (value
)));
191 g_type
= G_VALUE_TYPE (value
);
192 value_table
= g_type_value_table_peek (g_type
);
194 g_return_if_fail (strcmp (value_table
->collect_format
, "p") == 0);
196 memset (&cvalue
, 0, sizeof (cvalue
));
197 cvalue
.v_pointer
= instance
;
199 /* make sure value's value is free()d */
200 if (value_table
->value_free
)
201 value_table
->value_free (value
);
203 /* setup and collect */
204 value_meminit (value
, g_type
);
205 error_msg
= value_table
->collect_value (value
, 1, &cvalue
, 0);
208 g_warning ("%s: %s", G_STRLOC
, error_msg
);
211 /* we purposely leak the value here, it might not be
212 * in a sane state if an error condition occoured
214 value_meminit (value
, g_type
);
215 value_table
->value_init (value
);
219 static GValueTransform
220 transform_func_lookup (GType src_type
,
223 TransformEntry entry
;
225 entry
.src_type
= src_type
;
228 entry
.dest_type
= dest_type
;
233 e
= g_bsearch_array_lookup (&transform_array
, &entry
);
236 /* need to check that there hasn't been a change in value handling */
237 if (g_type_value_table_peek (entry
.dest_type
) == g_type_value_table_peek (dest_type
) &&
238 g_type_value_table_peek (entry
.src_type
) == g_type_value_table_peek (src_type
))
241 entry
.dest_type
= g_type_parent (entry
.dest_type
);
243 while (entry
.dest_type
);
245 entry
.src_type
= g_type_parent (entry
.src_type
);
247 while (entry
.src_type
);
253 transform_entries_cmp (gconstpointer bsearch_node1
,
254 gconstpointer bsearch_node2
)
256 const TransformEntry
*e1
= bsearch_node1
;
257 const TransformEntry
*e2
= bsearch_node2
;
258 gint cmp
= G_BSEARCH_ARRAY_CMP (e1
->src_type
, e2
->src_type
);
263 return G_BSEARCH_ARRAY_CMP (e1
->dest_type
, e2
->dest_type
);
267 g_value_register_transform_func (GType src_type
,
269 GValueTransform transform_func
)
271 TransformEntry entry
;
273 g_return_if_fail (G_TYPE_HAS_VALUE_TABLE (src_type
));
274 g_return_if_fail (G_TYPE_HAS_VALUE_TABLE (dest_type
));
275 g_return_if_fail (transform_func
!= NULL
);
277 if (transform_func_lookup (src_type
, dest_type
))
278 g_warning ("reregistering value transformation function (%p) for `%s' to `%s'",
280 g_type_name (src_type
),
281 g_type_name (dest_type
));
282 entry
.src_type
= src_type
;
283 entry
.dest_type
= dest_type
;
284 entry
.func
= transform_func
;
285 g_bsearch_array_insert (&transform_array
, &entry
, TRUE
);
289 g_value_type_transformable (GType src_type
,
292 g_return_val_if_fail (G_TYPE_IS_VALUE (src_type
), FALSE
);
293 g_return_val_if_fail (G_TYPE_IS_VALUE (dest_type
), FALSE
);
295 return (g_value_type_compatible (src_type
, dest_type
) ||
296 transform_func_lookup (src_type
, dest_type
) != NULL
);
300 g_value_type_compatible (GType src_type
,
303 g_return_val_if_fail (G_TYPE_IS_VALUE (src_type
), FALSE
);
304 g_return_val_if_fail (G_TYPE_IS_VALUE (dest_type
), FALSE
);
306 return (g_type_is_a (src_type
, dest_type
) &&
307 g_type_value_table_peek (dest_type
) == g_type_value_table_peek (src_type
));
311 g_value_transform (const GValue
*src_value
,
316 g_return_val_if_fail (G_IS_VALUE (src_value
), FALSE
);
317 g_return_val_if_fail (G_IS_VALUE (dest_value
), FALSE
);
319 dest_type
= G_VALUE_TYPE (dest_value
);
320 if (g_value_type_compatible (G_VALUE_TYPE (src_value
), dest_type
))
322 g_value_copy (src_value
, dest_value
);
328 GValueTransform transform
= transform_func_lookup (G_VALUE_TYPE (src_value
), dest_type
);
332 g_value_unset (dest_value
);
334 /* setup and transform */
335 value_meminit (dest_value
, dest_type
);
336 transform (src_value
, dest_value
);