add reserved fundamental ids for gtk types (for transition time). added
[platform/upstream/glib.git] / gobject / gtype.c
1 /* GObject - GLib Type, Object, Parameter and Signal Library
2  * Copyright (C) 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        "gtype.h"
20
21 #include        "genums.h"
22 #include        "gobject.h"
23 #include        <string.h>
24
25 #define FIXME_DISABLE_PREALLOCATIONS
26
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.
33  *
34  * TODO:
35  * - g_type_from_name() should do an ordered array lookup after fetching the
36  *   the quark, instead of a second hashtable lookup.
37  *
38  * FIXME:
39  * - force interface initialization for already existing classes
40  */
41
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)))
50
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;
59
60
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);
68
69
70 /* --- structures --- */
71 struct _TypeNode
72 {
73   GTypePlugin *plugin;
74   guint        n_children : 12;
75   guint        n_supers : 8;
76   guint        n_ifaces : 9;
77   guint        is_classed : 1;
78   guint        is_instantiatable : 1;
79   guint        is_iface : 1;
80   GType       *children;
81   TypeData    *data;
82   GQuark       qname;
83   GData       *static_gdata;
84   union {
85     IFaceEntry  *iface_entries;
86     IFaceHolder *iholders;
87   } private;
88   GType        supers[1]; /* flexible array */
89 };
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)
94
95 struct _IFaceHolder
96 {
97   GType           instance_type;
98   GInterfaceInfo *info;
99   GTypePlugin    *plugin;
100   IFaceHolder    *next;
101 };
102 struct _CommonData
103 {
104   guint             ref_count;
105 };
106 struct _IFaceData
107 {
108   CommonData         common;
109   guint              vtable_size;
110   GBaseInitFunc      vtable_init_base;
111   GBaseFinalizeFunc  vtable_finalize_base;
112 };
113 struct _ClassData
114 {
115   CommonData         common;
116   guint              class_size;
117   GBaseInitFunc      class_init_base;
118   GBaseFinalizeFunc  class_finalize_base;
119   GClassInitFunc     class_init;
120   GClassFinalizeFunc class_finalize;
121   gconstpointer      class_data;
122   gpointer           class;
123 };
124 struct _InstanceData
125 {
126   CommonData         common;
127   guint              class_size;
128   GBaseInitFunc      class_init_base;
129   GBaseFinalizeFunc  class_finalize_base;
130   GClassInitFunc     class_init;
131   GClassFinalizeFunc class_finalize;
132   gconstpointer      class_data;
133   gpointer           class;
134   guint16            instance_size;
135   guint16            n_preallocs;
136   GInstanceInitFunc  instance_init;
137   GMemChunk        *mem_chunk;
138 };
139 union _TypeData
140 {
141   CommonData         common;
142   IFaceData          iface;
143   ClassData          class;
144   InstanceData       instance;
145 };
146 struct _IFaceEntry
147 {
148   GType           iface_type;
149   GTypeInterface *vtable;
150 };
151
152
153 /* --- externs --- */
154 const char *g_log_domain_gobject = "GLib-Object";
155 GType       _g_type_fundamental_last = 0;
156
157
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;
162
163 static inline TypeNode*
164 LOOKUP_TYPE_NODE (register GType utype)
165 {
166   register GType ftype = G_TYPE_FUNDAMENTAL (utype);
167   register GType b_seqno = G_TYPE_BRANCH_SEQNO (utype);
168
169   if (ftype < G_TYPE_FUNDAMENTAL_LAST && b_seqno < g_branch_seqnos[ftype])
170     return g_type_nodes[ftype][b_seqno];
171   else
172     return NULL;
173 }
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))
177
178 static TypeNode*
179 type_node_any_new (TypeNode    *pnode,
180                    GType        ftype,
181                    const gchar *name,
182                    GTypePlugin *plugin,
183                    GTypeFlags   type_flags)
184 {
185   guint branch_last, n_supers = pnode ? pnode->n_supers + 1 : 0;
186   GType type;
187   TypeNode *node;
188   guint i, node_size = 0;
189
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));
194
195   if (!pnode)
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;
203
204   node->n_supers = n_supers;
205   if (!pnode)
206     {
207       node->supers[0] = type;
208       node->supers[1] = 0;
209
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);
213
214       node->n_ifaces = 0;
215       if (node->is_iface)
216         node->private.iholders = NULL;
217       else
218         node->private.iface_entries = NULL;
219     }
220   else
221     {
222       node->supers[0] = type;
223       memcpy (node->supers + 1, pnode->supers, sizeof (GType[1 + pnode->n_supers + 1]));
224
225       node->is_classed = pnode->is_classed;
226       node->is_instantiatable = pnode->is_instantiatable;
227       node->is_iface = pnode->is_iface;
228
229       if (node->is_iface)
230         {
231           node->n_ifaces = 0;
232           node->private.iholders = NULL;
233         }
234       else
235         {
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);
239         }
240       
241       i = pnode->n_children++;
242       pnode->children = g_renew (GType, pnode->children, pnode->n_children);
243       pnode->children[i] = type;
244     }
245
246   node->plugin = plugin;
247   node->n_children = 0;
248   node->children = NULL;
249   node->data = NULL;
250   node->qname = g_quark_from_string (name);
251   node->static_gdata = NULL;
252
253   g_hash_table_insert (g_type_nodes_ht,
254                        GUINT_TO_POINTER (node->qname),
255                        GUINT_TO_POINTER (type));
256
257   return node;
258 }
259
260 static inline GTypeFundamentalInfo*
261 type_node_fundamental_info (TypeNode *node)
262 {
263   GType ftype = G_TYPE_FUNDAMENTAL (NODE_TYPE (node));
264   
265   if (ftype != NODE_TYPE (node))
266     node = LOOKUP_TYPE_NODE (ftype);
267   
268   return node ? G_STRUCT_MEMBER_P (node, - sizeof (GTypeFundamentalInfo)) : NULL;
269 }
270
271 static TypeNode*
272 type_node_fundamental_new (GType        ftype,
273                            const gchar *name,
274                            GTypeFlags   type_flags)
275 {
276   GTypeFundamentalInfo *finfo;
277   TypeNode *node;
278   guint i, flast = G_TYPE_FUNDAMENTAL_LAST;
279   
280   g_assert (ftype == G_TYPE_FUNDAMENTAL (ftype));
281   
282   type_flags &= G_TYPE_FLAG_MASK;
283
284   _g_type_fundamental_last = MAX (_g_type_fundamental_last, ftype + 1);
285   if (G_TYPE_FUNDAMENTAL_LAST > flast)
286     {
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++)
290         {
291           g_type_nodes[i] = NULL;
292           g_branch_seqnos[i] = 0;
293         }
294     }
295   g_assert (g_branch_seqnos[ftype] == 0);
296
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;
300
301   return node;
302 }
303
304 static TypeNode*
305 type_node_new (TypeNode    *pnode,
306                const gchar *name,
307                GTypePlugin *plugin)
308
309 {
310   g_assert (pnode);
311   g_assert (pnode->n_supers < MAX_N_SUPERS);
312   g_assert (pnode->n_children < MAX_N_CHILDREN);
313
314   return type_node_any_new (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (pnode)), name, plugin, 0);
315 }
316
317 static inline IFaceEntry*
318 type_lookup_iface_entry (TypeNode       *node,
319                          TypeNode       *iface)
320 {
321   if (iface->is_iface && node->n_ifaces)
322     {
323       IFaceEntry *ifaces = node->private.iface_entries - 1;
324       guint n_ifaces = node->n_ifaces;
325       GType iface_type = NODE_TYPE (iface);
326
327       do                /* FIXME: should optimize iface lookups for <= 4 */
328         {
329           guint i;
330           IFaceEntry *check;
331
332           i = (n_ifaces + 1) / 2;
333           check = ifaces + i;
334           if (iface_type == check->iface_type)
335             return check;
336           else if (iface_type > check->iface_type)
337             {
338               n_ifaces -= i;
339               ifaces = check;
340             }
341           else /* if (iface_type < check->iface_type) */
342             n_ifaces = i - 1;
343         }
344       while (n_ifaces);
345     }
346
347   return NULL;
348 }
349
350 static inline gchar*
351 type_descriptive_name (GType type)
352 {
353   if (type)
354     {
355       gchar *name = g_type_name (type);
356
357       return name ? name : "<unknown>";
358     }
359   else
360     return "<invalid>";
361 }
362
363
364 /* --- type consistency checks --- */
365 static gboolean
366 check_plugin (GTypePlugin *plugin,
367               gboolean     need_complete_type_info,
368               gboolean     need_complete_interface_info,
369               const gchar *type_name)
370 {
371   if (!plugin)
372     {
373       g_warning ("plugin handle for type `%s' is NULL",
374                  type_name);
375       return FALSE;
376     }
377   if (!plugin->vtable)
378     {
379       g_warning ("plugin for type `%s' has no function table",
380                  type_name);
381       return FALSE;
382     }
383   if (!plugin->vtable->plugin_ref)
384     {
385       g_warning ("plugin for type `%s' has no plugin_ref() implementation",
386                  type_name);
387       return FALSE;
388     }
389   if (!plugin->vtable->plugin_unref)
390     {
391       g_warning ("plugin for type `%s' has no plugin_unref() implementation",
392                  type_name);
393       return FALSE;
394     }
395   if (need_complete_type_info && !plugin->vtable->complete_type_info)
396     {
397       g_warning ("plugin for type `%s' has no complete_type_info() implementation",
398                  type_name);
399       return FALSE;
400     }
401   if (need_complete_interface_info && !plugin->vtable->complete_interface_info)
402     {
403       g_warning ("plugin for type `%s' has no complete_interface_info() implementation",
404                  type_name);
405       return FALSE;
406     }
407   return TRUE;
408 }
409
410 static gboolean
411 check_type_name (const gchar *type_name)
412 {
413   static const gchar *extra_chars = "-_+";
414   const gchar *p = type_name;
415   gboolean name_valid;
416
417   if (!type_name[0] || !type_name[1] || !type_name[2])
418     {
419       g_warning ("type name `%s' is too short", type_name);
420       return FALSE;
421     }
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]));
429   if (!name_valid)
430     {
431       g_warning ("type name `%s' contains invalid characters", type_name);
432       return FALSE;
433     }
434   if (g_type_from_name (type_name))
435     {
436       g_warning ("cannot register existing type `%s'", type_name);
437       return FALSE;
438     }
439
440   return TRUE;
441 }
442
443 static gboolean
444 check_derivation (GType        parent_type,
445                   const gchar *type_name)
446 {
447   TypeNode *pnode = LOOKUP_TYPE_NODE (parent_type);
448   GTypeFundamentalInfo* finfo = type_node_fundamental_info (pnode);
449   
450   if (!pnode)
451     {
452       g_warning ("cannot derive type `%s' from invalid parent type `%s'",
453                  type_name,
454                  type_descriptive_name (parent_type));
455       return FALSE;
456     }
457   /* ensure flat derivability */
458   if (!(finfo->type_flags & G_TYPE_FLAG_DERIVABLE))
459     {
460       g_warning ("cannot derive `%s' from non-derivable parent type `%s'",
461                  type_name,
462                  NODE_NAME (pnode));
463       return FALSE;
464     }
465   /* ensure deep derivability */
466   if (parent_type != G_TYPE_FUNDAMENTAL (parent_type) &&
467       !(finfo->type_flags & G_TYPE_FLAG_DEEP_DERIVABLE))
468     {
469       g_warning ("cannot derive `%s' from non-fundamental parent type `%s'",
470                  type_name,
471                  NODE_NAME (pnode));
472       return FALSE;
473     }
474   
475   return TRUE;
476 }
477
478 static gboolean
479 check_type_info (TypeNode             *pnode,
480                  GType                 ftype,
481                  const gchar          *type_name,
482                  const GTypeInfo      *info)
483 {
484   GTypeFundamentalInfo *finfo = type_node_fundamental_info (LOOKUP_TYPE_NODE (ftype));
485   gboolean is_interface = G_TYPE_IS_INTERFACE (ftype);
486
487   /* check instance members */
488   if (!(finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
489       (info->instance_size || info->n_preallocs || info->instance_init))
490     {
491       if (pnode)
492         g_warning ("cannot instantiate `%s', derived from non-instantiatable parent type `%s'",
493                    type_name,
494                    NODE_NAME (pnode));
495       else
496         g_warning ("cannot instantiate `%s' as non-instantiatable fundamental",
497                    type_name);
498       return FALSE;
499     }
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))))
504     {
505       if (pnode)
506         g_warning ("cannot create class for `%s', derived from non-classed parent type `%s'",
507                    type_name,
508                    NODE_NAME (pnode));
509       else
510         g_warning ("cannot create class for `%s' as non-classed fundamental",
511                    type_name);
512       return FALSE;
513     }
514   /* check interface size */
515   if (is_interface && info->class_size < sizeof (GTypeInterface))
516     {
517       g_warning ("specified interface size for type `%s' is smaller than `GTypeInterface' size",
518                  type_name);
519       return FALSE;
520     }
521   /* check class size */
522   if (finfo->type_flags & G_TYPE_FLAG_CLASSED)
523     {
524       if (info->class_size < sizeof (GTypeClass))
525         {
526           g_warning ("specified class size for type `%s' is smaller than `GTypeClass' size",
527                      type_name);
528           return FALSE;
529         }
530       if (pnode && info->class_size < pnode->data->class.class_size)
531         {
532           g_warning ("specified class size for type `%s' is smaller "
533                      "than the parent type's `%s' class size",
534                      type_name,
535                      NODE_NAME (pnode));
536           return FALSE;
537         }
538     }
539   /* check instance size */
540   if (finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE)
541     {
542       if (info->instance_size < sizeof (GTypeInstance))
543         {
544           g_warning ("specified instance size for type `%s' is smaller than `GTypeInstance' size",
545                      type_name);
546           return FALSE;
547         }
548       if (pnode && info->instance_size < pnode->data->instance.instance_size)
549         {
550           g_warning ("specified instance size for type `%s' is smaller "
551                      "than the parent type's `%s' instance size",
552                      type_name,
553                      NODE_NAME (pnode));
554           return FALSE;
555         }
556     }
557
558   return TRUE;
559 }
560
561 static TypeNode*
562 find_conforming_type (TypeNode *pnode,
563                       TypeNode *iface)
564 {
565   TypeNode *node = NULL;
566   guint i;
567
568   if (type_lookup_iface_entry (pnode, iface))
569     return pnode;
570
571   for (i = 0; i < pnode->n_children && !node; i++)
572     node = find_conforming_type (LOOKUP_TYPE_NODE (pnode->children[i]), iface);
573
574   return node;
575 }
576
577 static gboolean
578 check_add_interface (GType instance_type,
579                      GType iface_type)
580 {
581   TypeNode *node = LOOKUP_TYPE_NODE (instance_type);
582   TypeNode *iface = LOOKUP_TYPE_NODE (iface_type);
583   TypeNode *tnode;
584
585   if (!node || !node->is_instantiatable)
586     {
587       g_warning ("cannot add interfaces to invalid (non-instantiatable) type `%s'",
588                  type_descriptive_name (instance_type));
589       return FALSE;
590     }
591   if (!iface || !iface->is_iface)
592     {
593       g_warning ("cannot add invalid (non-interface) type `%s' to type `%s'",
594                  type_descriptive_name (iface_type),
595                  NODE_NAME (node));
596       return FALSE;
597     }
598   tnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (iface));
599   if (NODE_PARENT_TYPE (tnode) && !type_lookup_iface_entry (node, tnode))
600     {
601       g_warning ("cannot add sub-interface `%s' to type `%s' which does not conform to super-interface `%s'",
602                  NODE_NAME (iface),
603                  NODE_NAME (node),
604                  NODE_NAME (tnode));
605       return FALSE;
606     }
607   tnode = find_conforming_type (node, iface);
608   if (tnode)
609     {
610       g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface",
611                  NODE_NAME (iface),
612                  NODE_NAME (node),
613                  NODE_NAME (tnode));
614       return FALSE;
615     }
616
617   return TRUE;
618 }
619
620 static gboolean
621 check_interface_info (TypeNode             *iface,
622                       GType                 instance_type,
623                       const GInterfaceInfo *info)
624 {
625   if ((info->interface_finalize || info->interface_data) && !info->interface_init)
626     {
627       g_warning ("interface type `%s' for type `%s' comes without initializer",
628                  NODE_NAME (iface),
629                  type_descriptive_name (instance_type));
630       return FALSE;
631     }
632
633   return TRUE;
634 }
635
636
637 /* --- type info (type node data) --- */
638 static void
639 type_data_make (TypeNode        *node,
640                 const GTypeInfo *info)
641 {
642   TypeData *data = NULL;
643
644   g_assert (node->data == NULL && info != NULL);
645   
646   if (node->is_instantiatable) /* carefull, is_instantiatable is also is_classed */
647     {
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;
660 #endif
661       data->instance.instance_init = info->instance_init;
662       data->instance.mem_chunk = NULL;
663     }
664   else if (node->is_classed) /* only classed */
665     {
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;
674     }
675   else if (node->is_iface)
676     {
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;
681     }
682   else
683     data = g_malloc0 (sizeof (CommonData));
684
685   node->data = data;
686   node->data->common.ref_count = 1;
687 }
688
689 static inline void
690 type_data_ref (TypeNode *node)
691 {
692   if (!node->data)
693     {
694       TypeNode *pnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (node));
695       GTypeInfo tmpinfo;
696       
697       g_assert (node->plugin != NULL);
698       
699       if (pnode)
700         type_data_ref (pnode);
701       
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);
707     }
708   else
709     {
710       g_assert (node->data->common.ref_count > 0);
711
712       node->data->common.ref_count += 1;
713     }
714 }
715
716 static inline void
717 type_data_unref (TypeNode *node)
718 {
719   g_assert (node->data && node->data->common.ref_count);
720
721   if (node->data->common.ref_count > 1)
722     node->data->common.ref_count -= 1;
723   else
724     {
725       if (!node->plugin)
726         {
727           g_warning ("static type `%s' unreferenced too often",
728                      NODE_NAME (node));
729           return;
730         }
731
732       type_data_last_unref (NODE_TYPE (node));
733     }
734 }
735
736 static void
737 type_node_add_iface_entry (TypeNode *node,
738                            GType     iface_type)
739 {
740   IFaceEntry *entries;
741   guint i;
742
743   g_assert (node->is_instantiatable && node->n_ifaces < MAX_N_IFACES);
744
745   node->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)
750       break;
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;
754
755   for (i = 0; i < node->n_children; i++)
756     type_node_add_iface_entry (LOOKUP_TYPE_NODE (node->children[i]), iface_type);
757 }
758
759 static void
760 type_add_interface (TypeNode       *node,
761                     TypeNode       *iface,
762                     GInterfaceInfo *info,
763                     GTypePlugin    *plugin)
764 {
765   IFaceHolder *iholder = g_new0 (IFaceHolder, 1);
766   
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
769    */
770   g_assert (node->is_instantiatable && iface->is_iface && ((info && !plugin) || (!info && plugin)));
771   
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;
777
778   type_node_add_iface_entry (node, NODE_TYPE (iface));
779 }
780
781 static IFaceHolder*
782 type_iface_retrive_holder_info (TypeNode *iface,
783                                 GType     instance_type)
784 {
785   IFaceHolder *iholder = iface->private.iholders;
786
787   g_assert (iface->is_iface);
788
789   while (iholder->instance_type != instance_type)
790     iholder = iholder->next;
791
792   if (!iholder->info)
793     {
794       GInterfaceInfo tmpinfo;
795       
796       g_assert (iholder->plugin != NULL);
797       
798       type_data_ref (iface);
799
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));
805     }
806   
807   return iholder;
808 }
809
810 static void
811 type_iface_blow_holder_info (TypeNode *iface,
812                              GType     instance_type)
813 {
814   IFaceHolder *iholder = iface->private.iholders;
815
816   g_assert (iface->is_iface);
817
818   while (iholder->instance_type != instance_type)
819     iholder = iholder->next;
820
821   if (iholder->info && iholder->plugin)
822     {
823       g_free (iholder->info);
824       iholder->info = NULL;
825       g_type_plugin_unref (iholder->plugin);
826
827       type_data_unref (iface);
828     }
829 }
830
831
832 /* --- type structure creation/destruction --- */
833 GTypeInstance*
834 g_type_create_instance (GType type)
835 {
836   TypeNode *node = LOOKUP_TYPE_NODE (type);
837   GTypeInstance *instance;
838   GTypeClass *class;
839   guint i;
840   
841   if (!node || !node->is_instantiatable)
842     {
843       g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
844                  type_descriptive_name (type));
845       return NULL;
846     }
847   
848   class = g_type_class_ref (type);
849   
850   if (node->data->instance.n_preallocs)
851     {
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),
857                                                           G_ALLOC_AND_FREE);
858       instance = g_chunk_new0 (GTypeInstance, node->data->instance.mem_chunk);
859     }
860   else
861     instance = g_malloc0 (node->data->instance.instance_size);
862   
863   for (i = node->n_supers; i > 0; i--)
864     {
865       TypeNode *pnode = LOOKUP_TYPE_NODE (node->supers[i]);
866       
867       if (pnode->data->instance.instance_init)
868         {
869           instance->g_class = pnode->data->instance.class;
870           pnode->data->instance.instance_init (instance, class);
871         }
872     }
873   instance->g_class = class;
874   if (node->data->instance.instance_init)
875     node->data->instance.instance_init (instance, class);
876
877   return instance;
878 }
879
880 void
881 g_type_free_instance (GTypeInstance *instance)
882 {
883   TypeNode *node;
884   GTypeClass *class;
885
886   g_return_if_fail (instance != NULL && instance->g_class != NULL);
887
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)
891     {
892       g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
893                  type_descriptive_name (class->g_type));
894       return;
895     }
896
897   instance->g_class = NULL;
898   if (node->data->instance.n_preallocs)
899     g_chunk_free (instance, node->data->instance.mem_chunk);
900   else
901     g_free (instance);
902
903   g_type_class_unref (class);
904 }
905
906 static void
907 type_propagate_iface_vtable (TypeNode       *pnode,
908                              TypeNode       *iface,
909                              GTypeInterface *vtable)
910 {
911   IFaceEntry *entry = type_lookup_iface_entry (pnode, iface);
912   guint i;
913
914   entry->vtable = vtable;
915   for (i = 0; i < pnode->n_children; i++)
916     {
917       TypeNode *node = LOOKUP_TYPE_NODE (pnode->children[i]);
918
919       type_propagate_iface_vtable (node, iface, vtable);
920     }
921 }
922
923 static void
924 type_iface_vtable_init (TypeNode       *iface,
925                         TypeNode       *node)
926 {
927   IFaceEntry *entry = type_lookup_iface_entry (node, iface);
928   IFaceHolder *iholder = type_iface_retrive_holder_info (iface, NODE_TYPE (node));
929   GTypeInterface *vtable;
930   
931   g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info);
932
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);
937
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);
942 }
943
944 static void
945 type_iface_vtable_finalize (TypeNode       *iface,
946                             TypeNode       *node,
947                             GTypeInterface *vtable)
948 {
949   IFaceEntry *entry = type_lookup_iface_entry (node, iface);
950   IFaceHolder *iholder = iface->private.iholders;
951
952   g_assert (entry && entry->vtable == vtable);
953
954   while (iholder->instance_type != NODE_TYPE (node))
955     iholder = iholder->next;
956   g_assert (iholder && iholder->info);
957
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);
963   
964   vtable->g_type = 0;
965   vtable->g_instance_type = 0;
966   g_free (vtable);
967
968   type_iface_blow_holder_info (iface, NODE_TYPE (node));
969 }
970
971 static void
972 type_class_init (TypeNode   *node,
973                  GTypeClass *pclass)
974 {
975   GSList *slist, *init_slist = NULL;
976   GTypeClass *class;
977   IFaceEntry *entry;
978   TypeNode *bnode;
979   guint i;
980   
981   g_assert (node->is_classed && node->data &&
982             node->data->class.class_size &&
983             !node->data->class.class);
984   
985   class = g_malloc0 (node->data->class.class_size);
986   node->data->class.class = class;
987   
988   if (pclass)
989     {
990       TypeNode *pnode = LOOKUP_TYPE_NODE (pclass->g_type);
991       
992       memcpy (class, pclass, pnode->data->class.class_size);
993     }
994   
995   class->g_type = NODE_TYPE (node);
996   
997   /* stack all base class initialization functions, so we
998    * call them in ascending order.
999    */
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)
1004     {
1005       GBaseInitFunc class_init_base = slist->data;
1006       
1007       class_init_base (class);
1008     }
1009   g_slist_free (init_slist);
1010   
1011   if (node->data->class.class_init)
1012     node->data->class.class_init (class, (gpointer) node->data->class.class_data);
1013
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;
1018   while (entry)
1019     {
1020       type_iface_vtable_init (LOOKUP_TYPE_NODE (entry->iface_type), node);
1021
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;
1025     }
1026 }
1027
1028 static void
1029 type_data_finalize_class_ifaces (TypeNode *node)
1030 {
1031   IFaceEntry *entry;
1032   guint i;
1033   
1034   g_assert (node->is_instantiatable && node->data && node->data->class.class && node->data->common.ref_count == 0);
1035   
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)));
1039
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;
1044   while (entry)
1045     {
1046       type_iface_vtable_finalize (LOOKUP_TYPE_NODE (entry->iface_type), node, entry->vtable);
1047
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;
1052     }
1053 }
1054
1055 static void
1056 type_data_finalize_class (TypeNode  *node,
1057                           ClassData *cdata)
1058 {
1059   GTypeClass *class = cdata->class;
1060   TypeNode *bnode;
1061   
1062   g_assert (cdata->class && cdata->common.ref_count == 0);
1063   
1064   g_message ("finalizing %sClass `%s'",
1065              type_descriptive_name (G_TYPE_FUNDAMENTAL (NODE_TYPE (node))),
1066              type_descriptive_name (NODE_TYPE (node)));
1067
1068   if (cdata->class_finalize)
1069     cdata->class_finalize (class, (gpointer) cdata->class_data);
1070   
1071   /* call all base class destruction functions in descending order
1072    */
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);
1078   
1079   class->g_type = 0;
1080   g_free (cdata->class);
1081 }
1082
1083 static void
1084 type_data_last_unref (GType type)
1085 {
1086   TypeNode *node = LOOKUP_TYPE_NODE (type);
1087   
1088   g_return_if_fail (node != NULL && node->plugin != NULL);
1089   
1090   if (!node->data || node->data->common.ref_count == 0)
1091     {
1092       g_warning ("cannot drop last reference to unreferenced type `%s'",
1093                  type_descriptive_name (type));
1094       return;
1095     }
1096   
1097   if (node->data->common.ref_count > 1) /* may have been re-referenced meanwhile */
1098     node->data->common.ref_count -= 1;
1099   else
1100     {
1101       GType ptype = NODE_PARENT_TYPE (node);
1102       
1103       node->data->common.ref_count = 0;
1104       
1105       if (node->is_instantiatable && node->data->instance.mem_chunk)
1106         {
1107           g_mem_chunk_destroy (node->data->instance.mem_chunk);
1108           node->data->instance.mem_chunk = NULL;
1109         }
1110       
1111       if (node->is_classed && node->data->class.class)
1112         {
1113           ClassData *cdata = &node->data->class;
1114
1115           if (node->n_ifaces)
1116             type_data_finalize_class_ifaces (node);
1117           node->data = NULL;
1118           type_data_finalize_class (node, cdata);
1119           g_free (cdata);
1120         }
1121       else
1122         {
1123           g_free (node->data);
1124           node->data = NULL;
1125         }
1126       
1127       if (ptype)
1128         type_data_unref (LOOKUP_TYPE_NODE (ptype));
1129       g_type_plugin_unref (node->plugin);
1130     }
1131 }
1132
1133
1134 /* --- type registration --- */
1135 GType
1136 g_type_register_fundamental (GType                       type_id,
1137                              const gchar                *type_name,
1138                              const GTypeFundamentalInfo *finfo,
1139                              const GTypeInfo            *info)
1140 {
1141   GTypeFundamentalInfo *node_finfo;
1142   TypeNode *node;
1143
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);
1148
1149   if (!check_type_name (type_name))
1150     return 0;
1151   if (G_TYPE_FUNDAMENTAL (type_id) != type_id)
1152     {
1153       g_warning ("cannot register fundamental type `%s' with non-fundamental id (%u)",
1154                  type_name,
1155                  type_id);
1156       return 0;
1157     }
1158   if (LOOKUP_TYPE_NODE (type_id))
1159     {
1160       g_warning ("cannot register existing fundamental type `%s' (as `%s')",
1161                  type_descriptive_name (type_id),
1162                  type_name);
1163       return 0;
1164     }
1165   if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
1166       !(finfo->type_flags & G_TYPE_FLAG_CLASSED))
1167     {
1168       g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
1169                  type_name);
1170       return 0;
1171     }
1172
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;
1177
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);
1181
1182   return NODE_TYPE (node);
1183 }
1184
1185 GType
1186 g_type_register_static (GType            parent_type,
1187                         const gchar     *type_name,
1188                         const GTypeInfo *info)
1189 {
1190   TypeNode *pnode, *node;
1191   GType type;
1192   
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);
1196   
1197   if (!check_type_name (type_name))
1198     return 0;
1199   if (!check_derivation (parent_type, type_name))
1200     return 0;
1201
1202   pnode = LOOKUP_TYPE_NODE (parent_type);
1203   type_data_ref (pnode);
1204
1205   if (!check_type_info (pnode, G_TYPE_FUNDAMENTAL (parent_type), type_name, info))
1206     return 0;
1207   if (info->class_finalize)
1208     {
1209       g_warning ("class destructor specified for static type `%s'",
1210                  type_name);
1211       return 0;
1212     }
1213
1214   node = type_node_new (pnode, type_name, NULL);
1215   type = NODE_TYPE (node);
1216   type_data_make (node, info);
1217
1218   return type;
1219 }
1220
1221 GType
1222 g_type_register_dynamic (GType        parent_type,
1223                          const gchar *type_name,
1224                          GTypePlugin *plugin)
1225 {
1226   TypeNode *pnode, *node;
1227   GType type;
1228
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);
1232
1233   if (!check_type_name (type_name))
1234     return 0;
1235   if (!check_derivation (parent_type, type_name))
1236     return 0;
1237   if (!check_plugin (plugin, TRUE, FALSE, type_name))
1238     return 0;
1239   pnode = LOOKUP_TYPE_NODE (parent_type);
1240
1241   node = type_node_new (pnode, type_name, plugin);
1242   type = NODE_TYPE (node);
1243
1244   return type;
1245 }
1246
1247 void
1248 g_type_add_interface_static (GType           instance_type,
1249                              GType           interface_type,
1250                              GInterfaceInfo *info)
1251 {
1252   TypeNode *node;
1253   TypeNode *iface;
1254   
1255   g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
1256   g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
1257
1258   if (!check_add_interface (instance_type, interface_type))
1259     return;
1260   node = LOOKUP_TYPE_NODE (instance_type);
1261   iface = LOOKUP_TYPE_NODE (interface_type);
1262   if (!check_interface_info (iface, NODE_TYPE (node), info))
1263     return;
1264   type_add_interface (node, iface, info, NULL);
1265 }
1266
1267 void
1268 g_type_add_interface_dynamic (GType        instance_type,
1269                               GType        interface_type,
1270                               GTypePlugin *plugin)
1271 {
1272   TypeNode *node;
1273   TypeNode *iface;
1274   
1275   g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
1276   g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
1277
1278   if (!check_add_interface (instance_type, interface_type))
1279     return;
1280   node = LOOKUP_TYPE_NODE (instance_type);
1281   iface = LOOKUP_TYPE_NODE (interface_type);
1282   if (!check_plugin (plugin, FALSE, TRUE, NODE_NAME (node)))
1283     return;
1284   type_add_interface (node, iface, NULL, plugin);
1285 }
1286
1287
1288 /* --- public API functions --- */
1289 gpointer
1290 g_type_class_ref (GType type)
1291 {
1292   TypeNode *node = LOOKUP_TYPE_NODE (type);
1293
1294   /* optimize for common code path
1295    */
1296   if (node && node->is_classed && node->data &&
1297       node->data->class.class && node->data->common.ref_count > 0)
1298     {
1299       type_data_ref (node);
1300
1301       return node->data->class.class;
1302     }
1303
1304   if (!node || !node->is_classed ||
1305       (node->data && node->data->common.ref_count < 1))
1306     {
1307       g_warning ("cannot retrive class for invalid (unclassed) type `%s'",
1308                  type_descriptive_name (type));
1309       return NULL;
1310     }
1311
1312   type_data_ref (node);
1313
1314   if (!node->data->class.class)
1315     {
1316       GType ptype = NODE_PARENT_TYPE (node);
1317       GTypeClass *pclass = ptype ? g_type_class_ref (ptype) : NULL;
1318
1319       type_class_init (node, pclass);
1320     }
1321
1322   return node->data->class.class;
1323 }
1324
1325 void
1326 g_type_class_unref (gpointer g_class)
1327 {
1328   TypeNode *node;
1329   GTypeClass *class = g_class;
1330
1331   g_return_if_fail (g_class != NULL);
1332
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);
1337   else
1338     g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
1339                type_descriptive_name (class->g_type));
1340 }
1341
1342 gpointer
1343 g_type_class_peek (GType type)
1344 {
1345   TypeNode *node = LOOKUP_TYPE_NODE (type);
1346
1347   if (node && node->is_classed && node->data && node->data->class.class) /* common.ref_count _may_ be 0 */
1348     return node->data->class.class;
1349   else
1350     return NULL;
1351 }
1352
1353 gpointer
1354 g_type_class_peek_parent (gpointer g_class)
1355 {
1356   TypeNode *node;
1357
1358   g_return_val_if_fail (g_class != NULL, NULL);
1359
1360   node = LOOKUP_TYPE_NODE (G_TYPE_FROM_CLASS (g_class));
1361   if (node && node->is_classed && node->data && NODE_PARENT_TYPE (node))
1362     {
1363       node = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (node));
1364
1365       return node->data->class.class;
1366     }
1367
1368   return NULL;
1369 }
1370
1371 gpointer
1372 g_type_interface_peek (gpointer instance_class,
1373                        GType    iface_type)
1374 {
1375   TypeNode *node;
1376   TypeNode *iface;
1377   GTypeClass *class = instance_class;
1378
1379   g_return_val_if_fail (instance_class != NULL, NULL);
1380
1381   node = LOOKUP_TYPE_NODE (class->g_type);
1382   iface = LOOKUP_TYPE_NODE (iface_type);
1383   if (node && node->is_instantiatable && iface)
1384     {
1385       IFaceEntry *entry = type_lookup_iface_entry (node, iface);
1386
1387       if (entry && entry->vtable)
1388         return entry->vtable;
1389     }
1390
1391   return NULL;
1392 }
1393
1394 gchar*
1395 g_type_name (GType type)
1396 {
1397   TypeNode *node = LOOKUP_TYPE_NODE (type);
1398   
1399   return node ? NODE_NAME (node) : NULL;
1400 }
1401
1402 GQuark
1403 g_type_qname (GType type)
1404 {
1405   TypeNode *node = LOOKUP_TYPE_NODE (type);
1406
1407   return node ? node->qname : 0;
1408 }
1409
1410 GType
1411 g_type_from_name (const gchar *name)
1412 {
1413   GQuark quark;
1414   
1415   g_return_val_if_fail (name != NULL, 0);
1416   
1417   quark = g_quark_try_string (name);
1418   if (quark)
1419     {
1420       GType type = GPOINTER_TO_UINT (g_hash_table_lookup (g_type_nodes_ht, GUINT_TO_POINTER (quark)));
1421       
1422       if (type)
1423         return type;
1424     }
1425   
1426   return 0;
1427 }
1428
1429 GType
1430 g_type_parent (GType type)
1431 {
1432   TypeNode *node = LOOKUP_TYPE_NODE (type);
1433
1434   return node ? NODE_PARENT_TYPE (node) : 0;
1435 }
1436
1437 GType
1438 g_type_next_base (GType type,
1439                   GType base_type)
1440 {
1441   TypeNode *node = LOOKUP_TYPE_NODE (type);
1442   
1443   if (node)
1444     {
1445       TypeNode *base_node = LOOKUP_TYPE_NODE (base_type);
1446       
1447       if (base_node && base_node->n_supers < node->n_supers)
1448         {
1449           guint n = node->n_supers - base_node->n_supers;
1450           
1451           if (node->supers[n] == base_type)
1452             return node->supers[n - 1];
1453         }
1454     }
1455   
1456   return 0;
1457 }
1458
1459 gboolean
1460 g_type_is_a (GType type,
1461              GType is_a_type)
1462 {
1463   if (type != is_a_type)
1464     {
1465       TypeNode *node = LOOKUP_TYPE_NODE (type);
1466
1467       if (node)
1468         {
1469           TypeNode *a_node = LOOKUP_TYPE_NODE (is_a_type);
1470
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;
1473         }
1474     }
1475   else
1476     return LOOKUP_TYPE_NODE (type) != NULL;
1477
1478   return FALSE;
1479 }
1480
1481 gboolean
1482 g_type_conforms_to (GType type,
1483                     GType iface_type)
1484 {
1485   if (type != iface_type)
1486     {
1487       TypeNode *node = LOOKUP_TYPE_NODE (type);
1488
1489       if (node)
1490         {
1491           TypeNode *iface_node = LOOKUP_TYPE_NODE (iface_type);
1492
1493           if (iface_node)
1494             {
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;
1499             }
1500         }
1501     }
1502   else
1503     {
1504       TypeNode *node = LOOKUP_TYPE_NODE (type);
1505
1506       return node && (node->is_iface || node->is_instantiatable);
1507     }
1508
1509   return FALSE;
1510 }
1511
1512 guint
1513 g_type_fundamental_branch_last (GType type)
1514 {
1515   GType ftype = G_TYPE_FUNDAMENTAL (type);
1516
1517   return ftype < G_TYPE_FUNDAMENTAL_LAST ? g_branch_seqnos[ftype] : 0;
1518 }
1519
1520 GType* /* free result */
1521 g_type_children (GType  type,
1522                  guint *n_children)
1523 {
1524   TypeNode *node = LOOKUP_TYPE_NODE (type);
1525   
1526   if (node)
1527     {
1528       GType *children = g_new (GType, node->n_children + 1);
1529       
1530       memcpy (children, node->children, sizeof (GType) * node->n_children);
1531       children[node->n_children] = 0;
1532       
1533       if (n_children)
1534         *n_children = node->n_children;
1535       
1536       return children;
1537     }
1538   else
1539     {
1540       if (n_children)
1541         *n_children = 0;
1542       
1543       return NULL;
1544     }
1545 }
1546
1547 GType* /* free result */
1548 g_type_interfaces (GType  type,
1549                    guint *n_interfaces)
1550 {
1551   TypeNode *node = LOOKUP_TYPE_NODE (type);
1552
1553   if (node && node->is_instantiatable)
1554     {
1555       GType *ifaces = g_new (GType, node->n_ifaces + 1);
1556       guint i;
1557
1558       for (i = 0; i < node->n_ifaces; i++)
1559         ifaces[i] = node->private.iface_entries[i].iface_type;
1560       ifaces[i] = 0;
1561
1562       if (n_interfaces)
1563         *n_interfaces = node->n_ifaces;
1564
1565       return ifaces;
1566     }
1567   else
1568     {
1569       if (n_interfaces)
1570         *n_interfaces = 0;
1571
1572       return NULL;
1573     }
1574 }
1575
1576 typedef struct _QData QData;
1577 struct _GData
1578 {
1579   guint  n_qdatas;
1580   QData *qdatas;
1581 };
1582 struct _QData
1583 {
1584   GQuark   quark;
1585   gpointer data;
1586 };
1587
1588 gpointer
1589 g_type_get_qdata (GType  type,
1590                   GQuark quark)
1591 {
1592   TypeNode *node = LOOKUP_TYPE_NODE (type);
1593   GData *gdata;
1594   
1595   g_return_val_if_fail (node != NULL, NULL);
1596
1597   gdata = node->static_gdata;
1598   if (quark && gdata && gdata->n_qdatas)
1599     {
1600       QData *qdatas = gdata->qdatas - 1;
1601       guint n_qdatas = gdata->n_qdatas;
1602
1603       do                /* FIXME: should optimize qdata lookups for <= 4 */
1604         {
1605           guint i;
1606           QData *check;
1607
1608           i = (n_qdatas + 1) / 2;
1609           check = qdatas + i;
1610           if (quark == check->quark)
1611             return check->data;
1612           else if (quark > check->quark)
1613             {
1614               n_qdatas -= i;
1615               qdatas = check;
1616             }
1617           else /* if (quark < check->quark) */
1618             n_qdatas = i - 1;
1619         }
1620       while (n_qdatas);
1621     }
1622
1623   return NULL;
1624 }
1625
1626 void
1627 g_type_set_qdata (GType    type,
1628                   GQuark   quark,
1629                   gpointer data)
1630 {
1631   TypeNode *node = LOOKUP_TYPE_NODE (type);
1632   GData *gdata;
1633   QData *qdata;
1634   guint i;
1635
1636   g_return_if_fail (node != NULL);
1637   g_return_if_fail (quark != 0);
1638
1639   /* setup qdata list if necessary */
1640   if (!node->static_gdata)
1641     node->static_gdata = g_new0 (GData, 1);
1642   gdata = node->static_gdata;
1643
1644   /* try resetting old data */
1645   qdata = gdata->qdatas;
1646   for (i = 0; i < gdata->n_qdatas; i++)
1647     if (qdata[i].quark == quark)
1648       {
1649         qdata[i].data = data;
1650         return;
1651       }
1652
1653   /* add new entry */
1654   gdata->n_qdatas++;
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)
1659       break;
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;
1663 }
1664
1665
1666 /* --- implementation details --- */
1667 gboolean
1668 g_type_check_flags (GType      type,
1669                     GTypeFlags flags)
1670 {
1671   TypeNode *node = LOOKUP_TYPE_NODE (type);
1672   
1673   flags &= G_TYPE_FLAG_MASK;
1674   if (node)
1675     {
1676       GTypeFundamentalInfo *finfo = type_node_fundamental_info (node);
1677       
1678       return (finfo->type_flags & flags) != 0;
1679     }
1680   
1681   return FALSE;
1682 }
1683
1684 gboolean
1685 g_type_is_dynamic (GType      type,
1686                    GTypeFlags flags)
1687 {
1688   TypeNode *node = LOOKUP_TYPE_NODE (type);
1689
1690   return node && node->plugin;
1691 }
1692
1693 gboolean
1694 g_type_instance_conforms_to (GTypeInstance *type_instance,
1695                              GType          iface_type)
1696 {
1697   return (type_instance && type_instance->g_class &&
1698           g_type_conforms_to (type_instance->g_class->g_type, iface_type));
1699 }
1700
1701 gboolean
1702 g_type_class_is_a (GTypeClass *type_class,
1703                    GType       is_a_type)
1704 {
1705   return (type_class && g_type_is_a (type_class->g_type, is_a_type));
1706 }
1707
1708 GTypeInstance*
1709 g_type_check_instance_cast (GTypeInstance *type_instance,
1710                             GType          iface_type)
1711 {
1712   if (!type_instance)
1713     {
1714       g_warning ("invalid cast from (NULL) pointer to `%s'",
1715                  type_descriptive_name (iface_type));
1716       return type_instance;
1717     }
1718   if (!type_instance->g_class)
1719     {
1720       g_warning ("invalid unclassed pointer in cast to `%s'",
1721                  type_descriptive_name (iface_type));
1722       return type_instance;
1723     }
1724   if (!G_TYPE_IS_CLASSED (type_instance->g_class->g_type))
1725     {
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;
1730     }
1731   if (!g_type_conforms_to (type_instance->g_class->g_type, iface_type))
1732     {
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;
1737     }
1738
1739   return type_instance;
1740 }
1741
1742 GTypeClass*
1743 g_type_check_class_cast (GTypeClass *type_class,
1744                          GType       is_a_type)
1745 {
1746   if (!type_class)
1747     {
1748       g_warning ("invalid class cast from (NULL) pointer to `%s'",
1749                  type_descriptive_name (is_a_type));
1750       return type_class;
1751     }
1752   if (!G_TYPE_IS_CLASSED (type_class->g_type))
1753     {
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));
1757       return type_class;
1758     }
1759   if (!g_type_is_a (type_class->g_type, is_a_type))
1760     {
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));
1764       return type_class;
1765     }
1766
1767   return type_class;
1768 }
1769
1770
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 */
1775
1776
1777 /* --- initialization --- */
1778 void
1779 g_type_init (void)
1780 {
1781   static TypeNode *type0_node = NULL;
1782   GTypeInfo info;
1783   TypeNode *node;
1784   GType type;
1785
1786   if (G_TYPE_FUNDAMENTAL_LAST)
1787     return;
1788
1789   /* type qname hash table */
1790   g_type_nodes_ht = g_hash_table_new (g_direct_hash, g_direct_equal);
1791
1792   /* invalid type G_TYPE_INVALID (0)
1793    */
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;
1799
1800   /* void type G_TYPE_NONE
1801    */
1802   node = type_node_fundamental_new (G_TYPE_NONE, "void", 0);
1803   type = NODE_TYPE (node);
1804   g_assert (type == G_TYPE_NONE);
1805
1806   /* interface fundamental type G_TYPE_INTERFACE (!classed)
1807    */
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);
1813
1814   /* G_TYPE_ENUM & G_TYPE_FLAGS
1815    */
1816   g_enum_types_init ();
1817
1818   /* G_TYPE_PARAM
1819    */
1820   g_param_types_init ();
1821
1822   /* G_TYPE_OBJECT
1823    */
1824   g_object_type_init ();
1825 }