1 /* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 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.
25 #define FIXME_DISABLE_PREALLOCATIONS
27 /* NOTE: some functions (some internal variants and exported ones)
28 * invalidate data portions of the TypeNodes. if external functions/callbacks
29 * are called, pointers to memory maintained by TypeNodes have to be looked up
30 * again. this affects most of the struct TypeNode fields, e.g. ->children or
31 * ->iface_entries (not ->supers[] as of recently), as all those memory portions can
32 * get realloc()ed during callback invocation.
35 * - g_type_from_name() should do an ordered array lookup after fetching the
36 * the quark, instead of a second hashtable lookup.
39 * - force interface initialization for already existing classes
42 #define G_TYPE_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
43 G_TYPE_FLAG_INSTANTIATABLE | \
44 G_TYPE_FLAG_DERIVABLE | \
45 G_TYPE_FLAG_DEEP_DERIVABLE)
46 #define g_type_plugin_ref(p) ((p)->vtable->plugin_ref (p))
47 #define g_type_plugin_unref(p) ((p)->vtable->plugin_unref (p))
48 #define g_type_plugin_complete_type_info(p,t,i) ((p)->vtable->complete_type_info ((p), (t), (i)))
49 #define g_type_plugin_complete_interface_info(p,f,t,i) ((p)->vtable->complete_interface_info ((p), (f), (t), (i)))
51 typedef struct _TypeNode TypeNode;
52 typedef struct _CommonData CommonData;
53 typedef struct _IFaceData IFaceData;
54 typedef struct _ClassData ClassData;
55 typedef struct _InstanceData InstanceData;
56 typedef union _TypeData TypeData;
57 typedef struct _IFaceEntry IFaceEntry;
58 typedef struct _IFaceHolder IFaceHolder;
61 /* --- prototypes --- */
62 static inline GTypeFundamentalInfo* type_node_fundamental_info (TypeNode *node);
63 static void type_data_make (TypeNode *node,
64 const GTypeInfo *info);
65 static inline void type_data_ref (TypeNode *node);
66 static inline void type_data_unref (TypeNode *node);
67 static void type_data_last_unref (GType type);
70 /* --- structures --- */
74 guint n_children : 12;
78 guint is_instantiatable : 1;
85 IFaceEntry *iface_entries;
86 IFaceHolder *iholders;
88 GType supers[1]; /* flexible array */
90 #define SIZEOF_BASE_TYPE_NODE() (G_STRUCT_OFFSET (TypeNode, supers))
91 #define MAX_N_SUPERS (255)
92 #define MAX_N_CHILDREN (4095)
93 #define MAX_N_IFACES (511)
110 GBaseInitFunc vtable_init_base;
111 GBaseFinalizeFunc vtable_finalize_base;
117 GBaseInitFunc class_init_base;
118 GBaseFinalizeFunc class_finalize_base;
119 GClassInitFunc class_init;
120 GClassFinalizeFunc class_finalize;
121 gconstpointer class_data;
128 GBaseInitFunc class_init_base;
129 GBaseFinalizeFunc class_finalize_base;
130 GClassInitFunc class_init;
131 GClassFinalizeFunc class_finalize;
132 gconstpointer class_data;
134 guint16 instance_size;
136 GInstanceInitFunc instance_init;
137 GMemChunk *mem_chunk;
144 InstanceData instance;
149 GTypeInterface *vtable;
153 /* --- externs --- */
154 const char *g_log_domain_gobject = "GLib-Object";
155 GType _g_type_fundamental_last = 0;
158 /* --- type nodes --- */
159 static GHashTable *g_type_nodes_ht = NULL;
160 static GType *g_branch_seqnos = NULL;
161 static TypeNode ***g_type_nodes = NULL;
163 static inline TypeNode*
164 LOOKUP_TYPE_NODE (register GType utype)
166 register GType ftype = G_TYPE_FUNDAMENTAL (utype);
167 register GType b_seqno = G_TYPE_BRANCH_SEQNO (utype);
169 if (ftype < G_TYPE_FUNDAMENTAL_LAST && b_seqno < g_branch_seqnos[ftype])
170 return g_type_nodes[ftype][b_seqno];
174 #define NODE_TYPE(node) (node->supers[0])
175 #define NODE_PARENT_TYPE(node) (node->supers[1])
176 #define NODE_NAME(node) (g_quark_to_string (node->qname))
179 type_node_any_new (TypeNode *pnode,
183 GTypeFlags type_flags)
185 guint branch_last, n_supers = pnode ? pnode->n_supers + 1 : 0;
188 guint i, node_size = 0;
190 branch_last = g_branch_seqnos[ftype]++;
191 type = G_TYPE_DERIVE_ID (ftype, branch_last);
192 if (!branch_last || g_bit_storage (branch_last - 1) < g_bit_storage (g_branch_seqnos[ftype] - 1))
193 g_type_nodes[ftype] = g_renew (TypeNode*, g_type_nodes[ftype], 1 << g_bit_storage (g_branch_seqnos[ftype] - 1));
196 node_size += sizeof (GTypeFundamentalInfo); /* fundamental type */
197 node_size += SIZEOF_BASE_TYPE_NODE (); /* TypeNode structure */
198 node_size += sizeof (GType[1 + n_supers + 1]); /* self + anchestors + 0 for ->supers[] */
199 node = g_malloc0 (node_size);
200 if (!pnode) /* fundamental type */
201 node = G_STRUCT_MEMBER_P (node, sizeof (GTypeFundamentalInfo));
202 g_type_nodes[ftype][branch_last] = node;
204 node->n_supers = n_supers;
207 node->supers[0] = type;
210 node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0;
211 node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0;
212 node->is_iface = G_TYPE_IS_INTERFACE (type);
216 node->private.iholders = NULL;
218 node->private.iface_entries = NULL;
222 node->supers[0] = type;
223 memcpy (node->supers + 1, pnode->supers, sizeof (GType[1 + pnode->n_supers + 1]));
225 node->is_classed = pnode->is_classed;
226 node->is_instantiatable = pnode->is_instantiatable;
227 node->is_iface = pnode->is_iface;
232 node->private.iholders = NULL;
236 node->n_ifaces = pnode->n_ifaces;
237 node->private.iface_entries = g_memdup (pnode->private.iface_entries,
238 sizeof (pnode->private.iface_entries[0]) * node->n_ifaces);
241 i = pnode->n_children++;
242 pnode->children = g_renew (GType, pnode->children, pnode->n_children);
243 pnode->children[i] = type;
246 node->plugin = plugin;
247 node->n_children = 0;
248 node->children = NULL;
250 node->qname = g_quark_from_string (name);
251 node->static_gdata = NULL;
253 g_hash_table_insert (g_type_nodes_ht,
254 GUINT_TO_POINTER (node->qname),
255 GUINT_TO_POINTER (type));
260 static inline GTypeFundamentalInfo*
261 type_node_fundamental_info (TypeNode *node)
263 GType ftype = G_TYPE_FUNDAMENTAL (NODE_TYPE (node));
265 if (ftype != NODE_TYPE (node))
266 node = LOOKUP_TYPE_NODE (ftype);
268 return node ? G_STRUCT_MEMBER_P (node, - sizeof (GTypeFundamentalInfo)) : NULL;
272 type_node_fundamental_new (GType ftype,
274 GTypeFlags type_flags)
276 GTypeFundamentalInfo *finfo;
278 guint i, flast = G_TYPE_FUNDAMENTAL_LAST;
280 g_assert (ftype == G_TYPE_FUNDAMENTAL (ftype));
282 type_flags &= G_TYPE_FLAG_MASK;
284 _g_type_fundamental_last = MAX (_g_type_fundamental_last, ftype + 1);
285 if (G_TYPE_FUNDAMENTAL_LAST > flast)
287 g_type_nodes = g_renew (TypeNode**, g_type_nodes, G_TYPE_FUNDAMENTAL_LAST);
288 g_branch_seqnos = g_renew (GType, g_branch_seqnos, G_TYPE_FUNDAMENTAL_LAST);
289 for (i = flast; i < G_TYPE_FUNDAMENTAL_LAST; i++)
291 g_type_nodes[i] = NULL;
292 g_branch_seqnos[i] = 0;
295 g_assert (g_branch_seqnos[ftype] == 0);
297 node = type_node_any_new (NULL, ftype, name, NULL, type_flags);
298 finfo = type_node_fundamental_info (node);
299 finfo->type_flags = type_flags;
305 type_node_new (TypeNode *pnode,
311 g_assert (pnode->n_supers < MAX_N_SUPERS);
312 g_assert (pnode->n_children < MAX_N_CHILDREN);
314 return type_node_any_new (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (pnode)), name, plugin, 0);
317 static inline IFaceEntry*
318 type_lookup_iface_entry (TypeNode *node,
321 if (iface->is_iface && node->n_ifaces)
323 IFaceEntry *ifaces = node->private.iface_entries - 1;
324 guint n_ifaces = node->n_ifaces;
325 GType iface_type = NODE_TYPE (iface);
327 do /* FIXME: should optimize iface lookups for <= 4 */
332 i = (n_ifaces + 1) / 2;
334 if (iface_type == check->iface_type)
336 else if (iface_type > check->iface_type)
341 else /* if (iface_type < check->iface_type) */
351 type_descriptive_name (GType type)
355 gchar *name = g_type_name (type);
357 return name ? name : "<unknown>";
364 /* --- type consistency checks --- */
366 check_plugin (GTypePlugin *plugin,
367 gboolean need_complete_type_info,
368 gboolean need_complete_interface_info,
369 const gchar *type_name)
373 g_warning ("plugin handle for type `%s' is NULL",
379 g_warning ("plugin for type `%s' has no function table",
383 if (!plugin->vtable->plugin_ref)
385 g_warning ("plugin for type `%s' has no plugin_ref() implementation",
389 if (!plugin->vtable->plugin_unref)
391 g_warning ("plugin for type `%s' has no plugin_unref() implementation",
395 if (need_complete_type_info && !plugin->vtable->complete_type_info)
397 g_warning ("plugin for type `%s' has no complete_type_info() implementation",
401 if (need_complete_interface_info && !plugin->vtable->complete_interface_info)
403 g_warning ("plugin for type `%s' has no complete_interface_info() implementation",
411 check_type_name (const gchar *type_name)
413 static const gchar *extra_chars = "-_+";
414 const gchar *p = type_name;
417 if (!type_name[0] || !type_name[1] || !type_name[2])
419 g_warning ("type name `%s' is too short", type_name);
422 /* check the first letter */
423 name_valid = (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || p[0] == '_';
424 for (p = type_name + 1; *p; p++)
425 name_valid &= ((p[0] >= 'A' && p[0] <= 'Z') ||
426 (p[0] >= 'a' && p[0] <= 'z') ||
427 (p[0] >= '0' && p[0] <= '9') ||
428 strchr (extra_chars, p[0]));
431 g_warning ("type name `%s' contains invalid characters", type_name);
434 if (g_type_from_name (type_name))
436 g_warning ("cannot register existing type `%s'", type_name);
444 check_derivation (GType parent_type,
445 const gchar *type_name)
447 TypeNode *pnode = LOOKUP_TYPE_NODE (parent_type);
448 GTypeFundamentalInfo* finfo = type_node_fundamental_info (pnode);
452 g_warning ("cannot derive type `%s' from invalid parent type `%s'",
454 type_descriptive_name (parent_type));
457 /* ensure flat derivability */
458 if (!(finfo->type_flags & G_TYPE_FLAG_DERIVABLE))
460 g_warning ("cannot derive `%s' from non-derivable parent type `%s'",
465 /* ensure deep derivability */
466 if (parent_type != G_TYPE_FUNDAMENTAL (parent_type) &&
467 !(finfo->type_flags & G_TYPE_FLAG_DEEP_DERIVABLE))
469 g_warning ("cannot derive `%s' from non-fundamental parent type `%s'",
479 check_type_info (TypeNode *pnode,
481 const gchar *type_name,
482 const GTypeInfo *info)
484 GTypeFundamentalInfo *finfo = type_node_fundamental_info (LOOKUP_TYPE_NODE (ftype));
485 gboolean is_interface = G_TYPE_IS_INTERFACE (ftype);
487 /* check instance members */
488 if (!(finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
489 (info->instance_size || info->n_preallocs || info->instance_init))
492 g_warning ("cannot instantiate `%s', derived from non-instantiatable parent type `%s'",
496 g_warning ("cannot instantiate `%s' as non-instantiatable fundamental",
500 /* check class & interface members */
501 if (!(finfo->type_flags & G_TYPE_FLAG_CLASSED) &&
502 (info->class_init || info->class_finalize || info->class_data ||
503 (!is_interface && (info->class_size || info->base_init || info->base_finalize))))
506 g_warning ("cannot create class for `%s', derived from non-classed parent type `%s'",
510 g_warning ("cannot create class for `%s' as non-classed fundamental",
514 /* check interface size */
515 if (is_interface && info->class_size < sizeof (GTypeInterface))
517 g_warning ("specified interface size for type `%s' is smaller than `GTypeInterface' size",
521 /* check class size */
522 if (finfo->type_flags & G_TYPE_FLAG_CLASSED)
524 if (info->class_size < sizeof (GTypeClass))
526 g_warning ("specified class size for type `%s' is smaller than `GTypeClass' size",
530 if (pnode && info->class_size < pnode->data->class.class_size)
532 g_warning ("specified class size for type `%s' is smaller "
533 "than the parent type's `%s' class size",
539 /* check instance size */
540 if (finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE)
542 if (info->instance_size < sizeof (GTypeInstance))
544 g_warning ("specified instance size for type `%s' is smaller than `GTypeInstance' size",
548 if (pnode && info->instance_size < pnode->data->instance.instance_size)
550 g_warning ("specified instance size for type `%s' is smaller "
551 "than the parent type's `%s' instance size",
562 find_conforming_type (TypeNode *pnode,
565 TypeNode *node = NULL;
568 if (type_lookup_iface_entry (pnode, iface))
571 for (i = 0; i < pnode->n_children && !node; i++)
572 node = find_conforming_type (LOOKUP_TYPE_NODE (pnode->children[i]), iface);
578 check_add_interface (GType instance_type,
581 TypeNode *node = LOOKUP_TYPE_NODE (instance_type);
582 TypeNode *iface = LOOKUP_TYPE_NODE (iface_type);
585 if (!node || !node->is_instantiatable)
587 g_warning ("cannot add interfaces to invalid (non-instantiatable) type `%s'",
588 type_descriptive_name (instance_type));
591 if (!iface || !iface->is_iface)
593 g_warning ("cannot add invalid (non-interface) type `%s' to type `%s'",
594 type_descriptive_name (iface_type),
598 tnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (iface));
599 if (NODE_PARENT_TYPE (tnode) && !type_lookup_iface_entry (node, tnode))
601 g_warning ("cannot add sub-interface `%s' to type `%s' which does not conform to super-interface `%s'",
607 tnode = find_conforming_type (node, iface);
610 g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface",
621 check_interface_info (TypeNode *iface,
623 const GInterfaceInfo *info)
625 if ((info->interface_finalize || info->interface_data) && !info->interface_init)
627 g_warning ("interface type `%s' for type `%s' comes without initializer",
629 type_descriptive_name (instance_type));
637 /* --- type info (type node data) --- */
639 type_data_make (TypeNode *node,
640 const GTypeInfo *info)
642 TypeData *data = NULL;
644 g_assert (node->data == NULL && info != NULL);
646 if (node->is_instantiatable) /* carefull, is_instantiatable is also is_classed */
648 data = g_malloc0 (sizeof (InstanceData));
649 data->instance.class_size = info->class_size;
650 data->instance.class_init_base = info->base_init;
651 data->instance.class_finalize_base = info->base_finalize;
652 data->instance.class_init = info->class_init;
653 data->instance.class_finalize = info->class_finalize;
654 data->instance.class_data = info->class_data;
655 data->instance.class = NULL;
656 data->instance.instance_size = info->instance_size;
657 data->instance.n_preallocs = MIN (info->n_preallocs, 1024);
658 #ifdef FIXME_DISABLE_PREALLOCATIONS
659 data->instance.n_preallocs = 0;
661 data->instance.instance_init = info->instance_init;
662 data->instance.mem_chunk = NULL;
664 else if (node->is_classed) /* only classed */
666 data = g_malloc0 (sizeof (ClassData));
667 data->class.class_size = info->class_size;
668 data->class.class_init_base = info->base_init;
669 data->class.class_finalize_base = info->base_finalize;
670 data->class.class_init = info->class_init;
671 data->class.class_finalize = info->class_finalize;
672 data->class.class_data = info->class_data;
673 data->class.class = NULL;
675 else if (node->is_iface)
677 data = g_malloc0 (sizeof (IFaceData));
678 data->iface.vtable_size = info->class_size;
679 data->iface.vtable_init_base = info->base_init;
680 data->iface.vtable_finalize_base = info->base_finalize;
683 data = g_malloc0 (sizeof (CommonData));
686 node->data->common.ref_count = 1;
690 type_data_ref (TypeNode *node)
694 TypeNode *pnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (node));
697 g_assert (node->plugin != NULL);
700 type_data_ref (pnode);
702 memset (&tmpinfo, 0, sizeof (tmpinfo));
703 g_type_plugin_ref (node->plugin);
704 g_type_plugin_complete_type_info (node->plugin, NODE_TYPE (node), &tmpinfo);
705 check_type_info (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), NODE_NAME (node), &tmpinfo);
706 type_data_make (node, &tmpinfo);
710 g_assert (node->data->common.ref_count > 0);
712 node->data->common.ref_count += 1;
717 type_data_unref (TypeNode *node)
719 g_assert (node->data && node->data->common.ref_count);
721 if (node->data->common.ref_count > 1)
722 node->data->common.ref_count -= 1;
727 g_warning ("static type `%s' unreferenced too often",
732 type_data_last_unref (NODE_TYPE (node));
737 type_node_add_iface_entry (TypeNode *node,
743 g_assert (node->is_instantiatable && node->n_ifaces < MAX_N_IFACES);
746 node->private.iface_entries = g_renew (IFaceEntry, node->private.iface_entries, node->n_ifaces);
747 entries = node->private.iface_entries;
748 for (i = 0; i < node->n_ifaces - 1; i++)
749 if (entries[i].iface_type > iface_type)
751 g_memmove (entries + i + 1, entries + i, sizeof (entries[0]) * (node->n_ifaces - i - 1));
752 entries[i].iface_type = iface_type;
753 entries[i].vtable = NULL;
755 for (i = 0; i < node->n_children; i++)
756 type_node_add_iface_entry (LOOKUP_TYPE_NODE (node->children[i]), iface_type);
760 type_add_interface (TypeNode *node,
762 GInterfaceInfo *info,
765 IFaceHolder *iholder = g_new0 (IFaceHolder, 1);
767 /* we must not call any functions of GInterfaceInfo from within here, since
768 * we got most probably called from _within_ a type registration function
770 g_assert (node->is_instantiatable && iface->is_iface && ((info && !plugin) || (!info && plugin)));
772 iholder->next = iface->private.iholders;
773 iface->private.iholders = iholder;
774 iholder->instance_type = NODE_TYPE (node);
775 iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
776 iholder->plugin = plugin;
778 type_node_add_iface_entry (node, NODE_TYPE (iface));
782 type_iface_retrive_holder_info (TypeNode *iface,
785 IFaceHolder *iholder = iface->private.iholders;
787 g_assert (iface->is_iface);
789 while (iholder->instance_type != instance_type)
790 iholder = iholder->next;
794 GInterfaceInfo tmpinfo;
796 g_assert (iholder->plugin != NULL);
798 type_data_ref (iface);
800 memset (&tmpinfo, 0, sizeof (tmpinfo));
801 g_type_plugin_ref (iholder->plugin);
802 g_type_plugin_complete_interface_info (iholder->plugin, NODE_TYPE (iface), instance_type, &tmpinfo);
803 check_interface_info (iface, instance_type, &tmpinfo);
804 iholder->info = g_memdup (&tmpinfo, sizeof (tmpinfo));
811 type_iface_blow_holder_info (TypeNode *iface,
814 IFaceHolder *iholder = iface->private.iholders;
816 g_assert (iface->is_iface);
818 while (iholder->instance_type != instance_type)
819 iholder = iholder->next;
821 if (iholder->info && iholder->plugin)
823 g_free (iholder->info);
824 iholder->info = NULL;
825 g_type_plugin_unref (iholder->plugin);
827 type_data_unref (iface);
832 /* --- type structure creation/destruction --- */
834 g_type_create_instance (GType type)
836 TypeNode *node = LOOKUP_TYPE_NODE (type);
837 GTypeInstance *instance;
841 if (!node || !node->is_instantiatable)
843 g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
844 type_descriptive_name (type));
848 class = g_type_class_ref (type);
850 if (node->data->instance.n_preallocs)
852 if (!node->data->instance.mem_chunk)
853 node->data->instance.mem_chunk = g_mem_chunk_new (NODE_NAME (node),
854 node->data->instance.instance_size,
855 (node->data->instance.instance_size *
856 node->data->instance.n_preallocs),
858 instance = g_chunk_new0 (GTypeInstance, node->data->instance.mem_chunk);
861 instance = g_malloc0 (node->data->instance.instance_size);
863 for (i = node->n_supers; i > 0; i--)
865 TypeNode *pnode = LOOKUP_TYPE_NODE (node->supers[i]);
867 if (pnode->data->instance.instance_init)
869 instance->g_class = pnode->data->instance.class;
870 pnode->data->instance.instance_init (instance, class);
873 instance->g_class = class;
874 if (node->data->instance.instance_init)
875 node->data->instance.instance_init (instance, class);
881 g_type_free_instance (GTypeInstance *instance)
886 g_return_if_fail (instance != NULL && instance->g_class != NULL);
888 class = instance->g_class;
889 node = LOOKUP_TYPE_NODE (class->g_type);
890 if (!node || !node->is_instantiatable || !node->data || node->data->class.class != (gpointer) class)
892 g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
893 type_descriptive_name (class->g_type));
897 instance->g_class = NULL;
898 if (node->data->instance.n_preallocs)
899 g_chunk_free (instance, node->data->instance.mem_chunk);
903 g_type_class_unref (class);
907 type_propagate_iface_vtable (TypeNode *pnode,
909 GTypeInterface *vtable)
911 IFaceEntry *entry = type_lookup_iface_entry (pnode, iface);
914 entry->vtable = vtable;
915 for (i = 0; i < pnode->n_children; i++)
917 TypeNode *node = LOOKUP_TYPE_NODE (pnode->children[i]);
919 type_propagate_iface_vtable (node, iface, vtable);
924 type_iface_vtable_init (TypeNode *iface,
927 IFaceEntry *entry = type_lookup_iface_entry (node, iface);
928 IFaceHolder *iholder = type_iface_retrive_holder_info (iface, NODE_TYPE (node));
929 GTypeInterface *vtable;
931 g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info);
933 vtable = g_malloc0 (iface->data->iface.vtable_size);
934 type_propagate_iface_vtable (node, iface, vtable);
935 vtable->g_type = NODE_TYPE (iface);
936 vtable->g_instance_type = NODE_TYPE (node);
938 if (iface->data->iface.vtable_init_base)
939 iface->data->iface.vtable_init_base (vtable);
940 if (iholder->info->interface_init)
941 iholder->info->interface_init (vtable, iholder->info->interface_data);
945 type_iface_vtable_finalize (TypeNode *iface,
947 GTypeInterface *vtable)
949 IFaceEntry *entry = type_lookup_iface_entry (node, iface);
950 IFaceHolder *iholder = iface->private.iholders;
952 g_assert (entry && entry->vtable == vtable);
954 while (iholder->instance_type != NODE_TYPE (node))
955 iholder = iholder->next;
956 g_assert (iholder && iholder->info);
958 type_propagate_iface_vtable (node, iface, NULL);
959 if (iholder->info->interface_finalize)
960 iholder->info->interface_finalize (vtable, iholder->info->interface_data);
961 if (iface->data->iface.vtable_finalize_base)
962 iface->data->iface.vtable_finalize_base (vtable);
965 vtable->g_instance_type = 0;
968 type_iface_blow_holder_info (iface, NODE_TYPE (node));
972 type_class_init (TypeNode *node,
975 GSList *slist, *init_slist = NULL;
981 g_assert (node->is_classed && node->data &&
982 node->data->class.class_size &&
983 !node->data->class.class);
985 class = g_malloc0 (node->data->class.class_size);
986 node->data->class.class = class;
990 TypeNode *pnode = LOOKUP_TYPE_NODE (pclass->g_type);
992 memcpy (class, pclass, pnode->data->class.class_size);
995 class->g_type = NODE_TYPE (node);
997 /* stack all base class initialization functions, so we
998 * call them in ascending order.
1000 for (bnode = node; bnode; bnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (bnode)))
1001 if (bnode->data->class.class_init_base)
1002 init_slist = g_slist_prepend (init_slist, bnode->data->class.class_init_base);
1003 for (slist = init_slist; slist; slist = slist->next)
1005 GBaseInitFunc class_init_base = slist->data;
1007 class_init_base (class);
1009 g_slist_free (init_slist);
1011 if (node->data->class.class_init)
1012 node->data->class.class_init (class, (gpointer) node->data->class.class_data);
1014 /* ok, we got the class done, now initialize all interfaces */
1015 for (entry = NULL, i = 0; i < node->n_ifaces; i++)
1016 if (!node->private.iface_entries[i].vtable)
1017 entry = node->private.iface_entries;
1020 type_iface_vtable_init (LOOKUP_TYPE_NODE (entry->iface_type), node);
1022 for (entry = NULL, i = 0; i < node->n_ifaces; i++)
1023 if (!node->private.iface_entries[i].vtable)
1024 entry = node->private.iface_entries;
1029 type_data_finalize_class_ifaces (TypeNode *node)
1034 g_assert (node->is_instantiatable && node->data && node->data->class.class && node->data->common.ref_count == 0);
1036 g_message ("finalizing interfaces for %sClass `%s'",
1037 type_descriptive_name (G_TYPE_FUNDAMENTAL (NODE_TYPE (node))),
1038 type_descriptive_name (NODE_TYPE (node)));
1040 for (entry = NULL, i = 0; i < node->n_ifaces; i++)
1041 if (node->private.iface_entries[i].vtable &&
1042 node->private.iface_entries[i].vtable->g_instance_type == NODE_TYPE (node))
1043 entry = node->private.iface_entries;
1046 type_iface_vtable_finalize (LOOKUP_TYPE_NODE (entry->iface_type), node, entry->vtable);
1048 for (entry = NULL, i = 0; i < node->n_ifaces; i++)
1049 if (node->private.iface_entries[i].vtable &&
1050 node->private.iface_entries[i].vtable->g_instance_type == NODE_TYPE (node))
1051 entry = node->private.iface_entries;
1056 type_data_finalize_class (TypeNode *node,
1059 GTypeClass *class = cdata->class;
1062 g_assert (cdata->class && cdata->common.ref_count == 0);
1064 g_message ("finalizing %sClass `%s'",
1065 type_descriptive_name (G_TYPE_FUNDAMENTAL (NODE_TYPE (node))),
1066 type_descriptive_name (NODE_TYPE (node)));
1068 if (cdata->class_finalize)
1069 cdata->class_finalize (class, (gpointer) cdata->class_data);
1071 /* call all base class destruction functions in descending order
1073 if (cdata->class_finalize_base)
1074 cdata->class_finalize_base (class);
1075 for (bnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (node)); bnode; bnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (bnode)))
1076 if (bnode->data->class.class_finalize_base)
1077 bnode->data->class.class_finalize_base (class);
1080 g_free (cdata->class);
1084 type_data_last_unref (GType type)
1086 TypeNode *node = LOOKUP_TYPE_NODE (type);
1088 g_return_if_fail (node != NULL && node->plugin != NULL);
1090 if (!node->data || node->data->common.ref_count == 0)
1092 g_warning ("cannot drop last reference to unreferenced type `%s'",
1093 type_descriptive_name (type));
1097 if (node->data->common.ref_count > 1) /* may have been re-referenced meanwhile */
1098 node->data->common.ref_count -= 1;
1101 GType ptype = NODE_PARENT_TYPE (node);
1103 node->data->common.ref_count = 0;
1105 if (node->is_instantiatable && node->data->instance.mem_chunk)
1107 g_mem_chunk_destroy (node->data->instance.mem_chunk);
1108 node->data->instance.mem_chunk = NULL;
1111 if (node->is_classed && node->data->class.class)
1113 ClassData *cdata = &node->data->class;
1116 type_data_finalize_class_ifaces (node);
1118 type_data_finalize_class (node, cdata);
1123 g_free (node->data);
1128 type_data_unref (LOOKUP_TYPE_NODE (ptype));
1129 g_type_plugin_unref (node->plugin);
1134 /* --- type registration --- */
1136 g_type_register_fundamental (GType type_id,
1137 const gchar *type_name,
1138 const GTypeFundamentalInfo *finfo,
1139 const GTypeInfo *info)
1141 GTypeFundamentalInfo *node_finfo;
1144 g_return_val_if_fail (type_id > 0, 0);
1145 g_return_val_if_fail (type_name != NULL, 0);
1146 g_return_val_if_fail (finfo != NULL, 0);
1147 g_return_val_if_fail (info != NULL, 0);
1149 if (!check_type_name (type_name))
1151 if (G_TYPE_FUNDAMENTAL (type_id) != type_id)
1153 g_warning ("cannot register fundamental type `%s' with non-fundamental id (%u)",
1158 if (LOOKUP_TYPE_NODE (type_id))
1160 g_warning ("cannot register existing fundamental type `%s' (as `%s')",
1161 type_descriptive_name (type_id),
1165 if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
1166 !(finfo->type_flags & G_TYPE_FLAG_CLASSED))
1168 g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
1173 node = type_node_fundamental_new (type_id, type_name, finfo->type_flags);
1174 node_finfo = type_node_fundamental_info (node);
1175 node_finfo->n_collect_bytes = finfo->n_collect_bytes; // FIXME: check max bytes
1176 node_finfo->param_collector = finfo->param_collector;
1178 if (!check_type_info (NULL, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), type_name, info))
1179 return NODE_TYPE (node);
1180 type_data_make (node, info);
1182 return NODE_TYPE (node);
1186 g_type_register_static (GType parent_type,
1187 const gchar *type_name,
1188 const GTypeInfo *info)
1190 TypeNode *pnode, *node;
1193 g_return_val_if_fail (parent_type > 0, 0);
1194 g_return_val_if_fail (type_name != NULL, 0);
1195 g_return_val_if_fail (info != NULL, 0);
1197 if (!check_type_name (type_name))
1199 if (!check_derivation (parent_type, type_name))
1202 pnode = LOOKUP_TYPE_NODE (parent_type);
1203 type_data_ref (pnode);
1205 if (!check_type_info (pnode, G_TYPE_FUNDAMENTAL (parent_type), type_name, info))
1207 if (info->class_finalize)
1209 g_warning ("class destructor specified for static type `%s'",
1214 node = type_node_new (pnode, type_name, NULL);
1215 type = NODE_TYPE (node);
1216 type_data_make (node, info);
1222 g_type_register_dynamic (GType parent_type,
1223 const gchar *type_name,
1224 GTypePlugin *plugin)
1226 TypeNode *pnode, *node;
1229 g_return_val_if_fail (parent_type > 0, 0);
1230 g_return_val_if_fail (type_name != NULL, 0);
1231 g_return_val_if_fail (plugin != NULL, 0);
1233 if (!check_type_name (type_name))
1235 if (!check_derivation (parent_type, type_name))
1237 if (!check_plugin (plugin, TRUE, FALSE, type_name))
1239 pnode = LOOKUP_TYPE_NODE (parent_type);
1241 node = type_node_new (pnode, type_name, plugin);
1242 type = NODE_TYPE (node);
1248 g_type_add_interface_static (GType instance_type,
1249 GType interface_type,
1250 GInterfaceInfo *info)
1255 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
1256 g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
1258 if (!check_add_interface (instance_type, interface_type))
1260 node = LOOKUP_TYPE_NODE (instance_type);
1261 iface = LOOKUP_TYPE_NODE (interface_type);
1262 if (!check_interface_info (iface, NODE_TYPE (node), info))
1264 type_add_interface (node, iface, info, NULL);
1268 g_type_add_interface_dynamic (GType instance_type,
1269 GType interface_type,
1270 GTypePlugin *plugin)
1275 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
1276 g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
1278 if (!check_add_interface (instance_type, interface_type))
1280 node = LOOKUP_TYPE_NODE (instance_type);
1281 iface = LOOKUP_TYPE_NODE (interface_type);
1282 if (!check_plugin (plugin, FALSE, TRUE, NODE_NAME (node)))
1284 type_add_interface (node, iface, NULL, plugin);
1288 /* --- public API functions --- */
1290 g_type_class_ref (GType type)
1292 TypeNode *node = LOOKUP_TYPE_NODE (type);
1294 /* optimize for common code path
1296 if (node && node->is_classed && node->data &&
1297 node->data->class.class && node->data->common.ref_count > 0)
1299 type_data_ref (node);
1301 return node->data->class.class;
1304 if (!node || !node->is_classed ||
1305 (node->data && node->data->common.ref_count < 1))
1307 g_warning ("cannot retrive class for invalid (unclassed) type `%s'",
1308 type_descriptive_name (type));
1312 type_data_ref (node);
1314 if (!node->data->class.class)
1316 GType ptype = NODE_PARENT_TYPE (node);
1317 GTypeClass *pclass = ptype ? g_type_class_ref (ptype) : NULL;
1319 type_class_init (node, pclass);
1322 return node->data->class.class;
1326 g_type_class_unref (gpointer g_class)
1329 GTypeClass *class = g_class;
1331 g_return_if_fail (g_class != NULL);
1333 node = LOOKUP_TYPE_NODE (class->g_type);
1334 if (node && node->is_classed && node->data &&
1335 node->data->class.class == class && node->data->common.ref_count > 0)
1336 type_data_unref (node);
1338 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
1339 type_descriptive_name (class->g_type));
1343 g_type_class_peek (GType type)
1345 TypeNode *node = LOOKUP_TYPE_NODE (type);
1347 if (node && node->is_classed && node->data && node->data->class.class) /* common.ref_count _may_ be 0 */
1348 return node->data->class.class;
1354 g_type_class_peek_parent (gpointer g_class)
1358 g_return_val_if_fail (g_class != NULL, NULL);
1360 node = LOOKUP_TYPE_NODE (G_TYPE_FROM_CLASS (g_class));
1361 if (node && node->is_classed && node->data && NODE_PARENT_TYPE (node))
1363 node = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (node));
1365 return node->data->class.class;
1372 g_type_interface_peek (gpointer instance_class,
1377 GTypeClass *class = instance_class;
1379 g_return_val_if_fail (instance_class != NULL, NULL);
1381 node = LOOKUP_TYPE_NODE (class->g_type);
1382 iface = LOOKUP_TYPE_NODE (iface_type);
1383 if (node && node->is_instantiatable && iface)
1385 IFaceEntry *entry = type_lookup_iface_entry (node, iface);
1387 if (entry && entry->vtable)
1388 return entry->vtable;
1395 g_type_name (GType type)
1397 TypeNode *node = LOOKUP_TYPE_NODE (type);
1399 return node ? NODE_NAME (node) : NULL;
1403 g_type_qname (GType type)
1405 TypeNode *node = LOOKUP_TYPE_NODE (type);
1407 return node ? node->qname : 0;
1411 g_type_from_name (const gchar *name)
1415 g_return_val_if_fail (name != NULL, 0);
1417 quark = g_quark_try_string (name);
1420 GType type = GPOINTER_TO_UINT (g_hash_table_lookup (g_type_nodes_ht, GUINT_TO_POINTER (quark)));
1430 g_type_parent (GType type)
1432 TypeNode *node = LOOKUP_TYPE_NODE (type);
1434 return node ? NODE_PARENT_TYPE (node) : 0;
1438 g_type_next_base (GType type,
1441 TypeNode *node = LOOKUP_TYPE_NODE (type);
1445 TypeNode *base_node = LOOKUP_TYPE_NODE (base_type);
1447 if (base_node && base_node->n_supers < node->n_supers)
1449 guint n = node->n_supers - base_node->n_supers;
1451 if (node->supers[n] == base_type)
1452 return node->supers[n - 1];
1460 g_type_is_a (GType type,
1463 if (type != is_a_type)
1465 TypeNode *node = LOOKUP_TYPE_NODE (type);
1469 TypeNode *a_node = LOOKUP_TYPE_NODE (is_a_type);
1471 if (a_node && a_node->n_supers <= node->n_supers)
1472 return node->supers[node->n_supers - a_node->n_supers] == is_a_type;
1476 return LOOKUP_TYPE_NODE (type) != NULL;
1482 g_type_conforms_to (GType type,
1485 if (type != iface_type)
1487 TypeNode *node = LOOKUP_TYPE_NODE (type);
1491 TypeNode *iface_node = LOOKUP_TYPE_NODE (iface_type);
1495 if (iface_node->is_iface && node->is_instantiatable)
1496 return type_lookup_iface_entry (node, iface_node) != NULL;
1497 else if (iface_node->n_supers <= node->n_supers)
1498 return node->supers[node->n_supers - iface_node->n_supers] == iface_type;
1504 TypeNode *node = LOOKUP_TYPE_NODE (type);
1506 return node && (node->is_iface || node->is_instantiatable);
1513 g_type_fundamental_branch_last (GType type)
1515 GType ftype = G_TYPE_FUNDAMENTAL (type);
1517 return ftype < G_TYPE_FUNDAMENTAL_LAST ? g_branch_seqnos[ftype] : 0;
1520 GType* /* free result */
1521 g_type_children (GType type,
1524 TypeNode *node = LOOKUP_TYPE_NODE (type);
1528 GType *children = g_new (GType, node->n_children + 1);
1530 memcpy (children, node->children, sizeof (GType) * node->n_children);
1531 children[node->n_children] = 0;
1534 *n_children = node->n_children;
1547 GType* /* free result */
1548 g_type_interfaces (GType type,
1549 guint *n_interfaces)
1551 TypeNode *node = LOOKUP_TYPE_NODE (type);
1553 if (node && node->is_instantiatable)
1555 GType *ifaces = g_new (GType, node->n_ifaces + 1);
1558 for (i = 0; i < node->n_ifaces; i++)
1559 ifaces[i] = node->private.iface_entries[i].iface_type;
1563 *n_interfaces = node->n_ifaces;
1576 typedef struct _QData QData;
1589 g_type_get_qdata (GType type,
1592 TypeNode *node = LOOKUP_TYPE_NODE (type);
1595 g_return_val_if_fail (node != NULL, NULL);
1597 gdata = node->static_gdata;
1598 if (quark && gdata && gdata->n_qdatas)
1600 QData *qdatas = gdata->qdatas - 1;
1601 guint n_qdatas = gdata->n_qdatas;
1603 do /* FIXME: should optimize qdata lookups for <= 4 */
1608 i = (n_qdatas + 1) / 2;
1610 if (quark == check->quark)
1612 else if (quark > check->quark)
1617 else /* if (quark < check->quark) */
1627 g_type_set_qdata (GType type,
1631 TypeNode *node = LOOKUP_TYPE_NODE (type);
1636 g_return_if_fail (node != NULL);
1637 g_return_if_fail (quark != 0);
1639 /* setup qdata list if necessary */
1640 if (!node->static_gdata)
1641 node->static_gdata = g_new0 (GData, 1);
1642 gdata = node->static_gdata;
1644 /* try resetting old data */
1645 qdata = gdata->qdatas;
1646 for (i = 0; i < gdata->n_qdatas; i++)
1647 if (qdata[i].quark == quark)
1649 qdata[i].data = data;
1655 gdata->qdatas = g_renew (QData, gdata->qdatas, gdata->n_qdatas);
1656 qdata = gdata->qdatas;
1657 for (i = 0; i < gdata->n_qdatas - 1; i++)
1658 if (qdata[i].quark > quark)
1660 g_memmove (qdata + i + 1, qdata + i, sizeof (qdata[0]) * (gdata->n_qdatas - i - 1));
1661 qdata[i].quark = quark;
1662 qdata[i].data = data;
1666 /* --- implementation details --- */
1668 g_type_check_flags (GType type,
1671 TypeNode *node = LOOKUP_TYPE_NODE (type);
1673 flags &= G_TYPE_FLAG_MASK;
1676 GTypeFundamentalInfo *finfo = type_node_fundamental_info (node);
1678 return (finfo->type_flags & flags) != 0;
1685 g_type_is_dynamic (GType type,
1688 TypeNode *node = LOOKUP_TYPE_NODE (type);
1690 return node && node->plugin;
1694 g_type_instance_conforms_to (GTypeInstance *type_instance,
1697 return (type_instance && type_instance->g_class &&
1698 g_type_conforms_to (type_instance->g_class->g_type, iface_type));
1702 g_type_class_is_a (GTypeClass *type_class,
1705 return (type_class && g_type_is_a (type_class->g_type, is_a_type));
1709 g_type_check_instance_cast (GTypeInstance *type_instance,
1714 g_warning ("invalid cast from (NULL) pointer to `%s'",
1715 type_descriptive_name (iface_type));
1716 return type_instance;
1718 if (!type_instance->g_class)
1720 g_warning ("invalid unclassed pointer in cast to `%s'",
1721 type_descriptive_name (iface_type));
1722 return type_instance;
1724 if (!G_TYPE_IS_CLASSED (type_instance->g_class->g_type))
1726 g_warning ("invalid unclassed type `%s' in cast to `%s'",
1727 type_descriptive_name (type_instance->g_class->g_type),
1728 type_descriptive_name (iface_type));
1729 return type_instance;
1731 if (!g_type_conforms_to (type_instance->g_class->g_type, iface_type))
1733 g_warning ("invalid cast from `%s' to `%s'",
1734 type_descriptive_name (type_instance->g_class->g_type),
1735 type_descriptive_name (iface_type));
1736 return type_instance;
1739 return type_instance;
1743 g_type_check_class_cast (GTypeClass *type_class,
1748 g_warning ("invalid class cast from (NULL) pointer to `%s'",
1749 type_descriptive_name (is_a_type));
1752 if (!G_TYPE_IS_CLASSED (type_class->g_type))
1754 g_warning ("invalid unclassed type `%s' in class cast to `%s'",
1755 type_descriptive_name (type_class->g_type),
1756 type_descriptive_name (is_a_type));
1759 if (!g_type_is_a (type_class->g_type, is_a_type))
1761 g_warning ("invalid class cast from `%s' to `%s'",
1762 type_descriptive_name (type_class->g_type),
1763 type_descriptive_name (is_a_type));
1771 /* --- foreign prototypes --- */
1772 extern void g_param_types_init (void); /* sync with glib-gparam.c */
1773 extern void g_enum_types_init (void); /* sync with glib-genums.c */
1774 extern void g_object_type_init (void); /* sync with glib-gobject.c */
1777 /* --- initialization --- */
1781 static TypeNode *type0_node = NULL;
1786 if (G_TYPE_FUNDAMENTAL_LAST)
1789 /* type qname hash table */
1790 g_type_nodes_ht = g_hash_table_new (g_direct_hash, g_direct_equal);
1792 /* invalid type G_TYPE_INVALID (0)
1794 _g_type_fundamental_last = 1;
1795 g_type_nodes = g_renew (TypeNode**, g_type_nodes, G_TYPE_FUNDAMENTAL_LAST);
1796 g_type_nodes[0] = &type0_node;
1797 g_branch_seqnos = g_renew (GType, g_branch_seqnos, G_TYPE_FUNDAMENTAL_LAST);
1798 g_branch_seqnos[0] = 1;
1800 /* void type G_TYPE_NONE
1802 node = type_node_fundamental_new (G_TYPE_NONE, "void", 0);
1803 type = NODE_TYPE (node);
1804 g_assert (type == G_TYPE_NONE);
1806 /* interface fundamental type G_TYPE_INTERFACE (!classed)
1808 memset (&info, 0, sizeof (info));
1809 node = type_node_fundamental_new (G_TYPE_INTERFACE, "GInterface", G_TYPE_FLAG_DERIVABLE);
1810 type = NODE_TYPE (node);
1811 type_data_make (node, &info);
1812 g_assert (type == G_TYPE_INTERFACE);
1814 /* G_TYPE_ENUM & G_TYPE_FLAGS
1816 g_enum_types_init ();
1820 g_param_types_init ();
1824 g_object_type_init ();