1 /* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 2000 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.
21 #include "gbsearcharray.h"
23 #include "gvaluecollector.h"
27 /* --- typedefs & structures --- */
36 /* --- prototypes --- */
37 static gint
boxed_nodes_cmp (gconstpointer p1
,
41 /* --- variables --- */
42 static GBSearchArray boxed_bsa
= { boxed_nodes_cmp
, sizeof (BoxedNode
), 0, 0, NULL
};
45 /* --- functions --- */
47 boxed_nodes_cmp (gconstpointer p1
,
50 const BoxedNode
*node1
= p1
, *node2
= p2
;
52 return G_BSEARCH_ARRAY_CMP (node1
->type
, node2
->type
);
56 g_boxed_type_init (void) /* sync with gtype.c */
58 static const GTypeInfo info
= {
61 NULL
, /* base_destroy */
62 NULL
, /* class_init */
63 NULL
, /* class_destroy */
64 NULL
, /* class_data */
65 0, /* instance_size */
67 NULL
, /* instance_init */
68 NULL
, /* value_table */
70 const GTypeFundamentalInfo finfo
= { G_TYPE_FLAG_DERIVABLE
, };
75 type
= g_type_register_fundamental (G_TYPE_BOXED
, "GBoxed", &info
, &finfo
, G_TYPE_FLAG_ABSTRACT
);
76 g_assert (type
== G_TYPE_BOXED
);
80 boxed_proxy_value_init (GValue
*value
)
82 value
->data
[0].v_pointer
= 0;
86 boxed_proxy_value_free (GValue
*value
)
88 if (value
->data
[0].v_pointer
&& !(value
->data
[1].v_uint
& G_VALUE_STATIC_TAG
))
92 key
.type
= value
->g_type
;
93 node
= g_bsearch_array_lookup (&boxed_bsa
, &key
);
94 node
->free (value
->data
[0].v_pointer
);
99 boxed_proxy_value_copy (const GValue
*src_value
,
102 if (src_value
->data
[0].v_pointer
)
104 BoxedNode key
, *node
;
106 key
.type
= src_value
->g_type
;
107 node
= g_bsearch_array_lookup (&boxed_bsa
, &key
);
108 dest_value
->data
[0].v_pointer
= node
->copy (src_value
->data
[0].v_pointer
);
111 dest_value
->data
[0].v_pointer
= src_value
->data
[0].v_pointer
;
115 boxed_proxy_value_peek_pointer (const GValue
*value
)
117 return value
->data
[0].v_pointer
;
121 boxed_proxy_collect_value (GValue
*value
,
124 GTypeCValue
*collect_value
)
126 BoxedNode key
, *node
;
128 key
.type
= value
->g_type
;
129 node
= g_bsearch_array_lookup (&boxed_bsa
, &key
);
130 value
->data
[0].v_pointer
= node
->copy (collect_value
->v_pointer
);
137 boxed_proxy_lcopy_value (const GValue
*value
,
140 GTypeCValue
*collect_value
)
142 BoxedNode key
, *node
;
143 gpointer
*boxed_p
= collect_value
->v_pointer
;
146 return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value
));
148 key
.type
= value
->g_type
;
149 node
= g_bsearch_array_lookup (&boxed_bsa
, &key
);
150 *boxed_p
= node
->copy (value
->data
[0].v_pointer
);
157 g_boxed_type_register_static (const gchar
*name
,
158 GBoxedCopyFunc boxed_copy
,
159 GBoxedFreeFunc boxed_free
)
161 static const GTypeValueTable vtable
= {
162 boxed_proxy_value_init
,
163 boxed_proxy_value_free
,
164 boxed_proxy_value_copy
,
165 boxed_proxy_value_peek_pointer
,
166 G_VALUE_COLLECT_POINTER
,
167 boxed_proxy_collect_value
,
168 G_VALUE_COLLECT_POINTER
,
169 boxed_proxy_lcopy_value
,
171 static const GTypeInfo type_info
= {
173 NULL
, /* base_init */
174 NULL
, /* base_finalize */
175 NULL
, /* class_init */
176 NULL
, /* class_finalize */
177 NULL
, /* class_data */
178 0, /* instance_size */
180 NULL
, /* instance_init */
181 &vtable
, /* value_table */
185 g_return_val_if_fail (name
!= NULL
, 0);
186 g_return_val_if_fail (boxed_copy
!= NULL
, 0);
187 g_return_val_if_fail (boxed_free
!= NULL
, 0);
188 g_return_val_if_fail (g_type_from_name (name
) == 0, 0);
190 type
= g_type_register_static (G_TYPE_BOXED
, name
, &type_info
, 0);
192 /* install proxy functions upon successfull registration */
198 key
.copy
= boxed_copy
;
199 key
.free
= boxed_free
;
200 g_bsearch_array_insert (&boxed_bsa
, &key
, TRUE
);
207 g_boxed_copy (GType boxed_type
,
208 gconstpointer src_boxed
)
210 GTypeValueTable
*value_table
;
213 g_return_val_if_fail (G_TYPE_IS_BOXED (boxed_type
), NULL
);
214 g_return_val_if_fail (G_TYPE_IS_ABSTRACT (boxed_type
) == FALSE
, NULL
);
215 g_return_val_if_fail (src_boxed
!= NULL
, NULL
);
217 value_table
= g_type_value_table_peek (boxed_type
);
219 g_return_val_if_fail (G_TYPE_IS_VALUE_TYPE (boxed_type
), NULL
);
221 /* check if our proxying implementation is used, we can short-cut here */
222 if (value_table
->value_copy
== boxed_proxy_value_copy
)
224 BoxedNode key
, *node
;
226 key
.type
= boxed_type
;
227 node
= g_bsearch_array_lookup (&boxed_bsa
, &key
);
228 dest_boxed
= node
->copy ((gpointer
) src_boxed
);
232 GValue src_value
, dest_value
;
234 /* we heavil rely on the gvalue.c implementation here */
236 memset (&src_value
.data
, 0, sizeof (src_value
.data
));
237 memset (&dest_value
.data
, 0, sizeof (dest_value
.data
));
238 dest_value
.g_type
= boxed_type
;
239 src_value
.g_type
= boxed_type
;
240 src_value
.data
[0].v_pointer
= (gpointer
) src_boxed
;
241 value_table
->value_copy (&src_value
, &dest_value
);
242 if (dest_value
.data
[1].v_ulong
||
243 dest_value
.data
[2].v_ulong
||
244 dest_value
.data
[3].v_ulong
)
245 g_warning ("the copy_value() implementation of type `%s' seems to make use of reserved GValue fields",
246 g_type_name (boxed_type
));
248 dest_boxed
= dest_value
.data
[0].v_pointer
;
255 g_boxed_free (GType boxed_type
,
258 GTypeValueTable
*value_table
;
260 g_return_if_fail (G_TYPE_IS_BOXED (boxed_type
));
261 g_return_if_fail (G_TYPE_IS_ABSTRACT (boxed_type
) == FALSE
);
262 g_return_if_fail (boxed
!= NULL
);
264 value_table
= g_type_value_table_peek (boxed_type
);
266 g_return_if_fail (G_TYPE_IS_VALUE_TYPE (boxed_type
));
268 /* check if our proxying implementation is used, we can short-cut here */
269 if (value_table
->value_free
== boxed_proxy_value_free
)
271 BoxedNode key
, *node
;
273 key
.type
= boxed_type
;
274 node
= g_bsearch_array_lookup (&boxed_bsa
, &key
);
281 /* we heavil rely on the gvalue.c implementation here */
282 memset (&value
.data
, 0, sizeof (value
.data
));
283 value
.g_type
= boxed_type
;
284 value
.data
[0].v_pointer
= boxed
;
285 value_table
->value_free (&value
);
290 g_value_set_boxed (GValue
*value
,
293 g_return_if_fail (G_IS_VALUE_BOXED (value
));
294 g_return_if_fail (G_TYPE_IS_VALUE (G_VALUE_TYPE (value
)));
296 if (value
->data
[0].v_pointer
&& !(value
->data
[1].v_uint
& G_VALUE_STATIC_TAG
))
297 g_boxed_free (G_VALUE_TYPE (value
), value
->data
[0].v_pointer
);
298 value
->data
[0].v_pointer
= boxed
? g_boxed_copy (G_VALUE_TYPE (value
), boxed
) : NULL
;
299 value
->data
[1].v_uint
= 0;
303 g_value_set_static_boxed (GValue
*value
,
306 g_return_if_fail (G_IS_VALUE_BOXED (value
));
307 g_return_if_fail (G_TYPE_IS_VALUE (G_VALUE_TYPE (value
)));
309 if (value
->data
[0].v_pointer
&& !(value
->data
[1].v_uint
& G_VALUE_STATIC_TAG
))
310 g_boxed_free (G_VALUE_TYPE (value
), value
->data
[0].v_pointer
);
311 value
->data
[0].v_pointer
= (gpointer
) boxed
;
312 value
->data
[1].v_uint
= boxed
? G_VALUE_STATIC_TAG
: 0;
316 g_value_get_boxed (const GValue
*value
)
318 g_return_val_if_fail (G_IS_VALUE_BOXED (value
), NULL
);
319 g_return_val_if_fail (G_TYPE_IS_VALUE (G_VALUE_TYPE (value
)), NULL
);
321 return value
->data
[0].v_pointer
;
325 g_value_dup_boxed (GValue
*value
)
327 g_return_val_if_fail (G_IS_VALUE_BOXED (value
), NULL
);
328 g_return_val_if_fail (G_TYPE_IS_VALUE (G_VALUE_TYPE (value
)), NULL
);
330 return value
->data
[0].v_pointer
? g_boxed_copy (G_VALUE_TYPE (value
), value
->data
[0].v_pointer
) : NULL
;