removed g_type_is_dynamic() and added g_type_get_plugin().
[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        <string.h>
22
23 #define FIXME_DISABLE_PREALLOCATIONS
24
25 /* NOTE: some functions (some internal variants and exported ones)
26  * invalidate data portions of the TypeNodes. if external functions/callbacks
27  * are called, pointers to memory maintained by TypeNodes have to be looked up
28  * again. this affects most of the struct TypeNode fields, e.g. ->children or
29  * ->iface_entries (not ->supers[] as of recently), as all those memory portions can
30  * get realloc()ed during callback invocation.
31  *
32  * TODO:
33  * - g_type_from_name() should do an ordered array lookup after fetching the
34  *   the quark, instead of a second hashtable lookup.
35  *
36  * FIXME:
37  * - force interface initialization for already existing classes
38  */
39
40 #define G_TYPE_FLAG_MASK        (G_TYPE_FLAG_CLASSED | \
41                                  G_TYPE_FLAG_INSTANTIATABLE | \
42                                  G_TYPE_FLAG_DERIVABLE | \
43                                  G_TYPE_FLAG_DEEP_DERIVABLE)
44 #define g_type_plugin_ref(p)                            ((p)->vtable->plugin_ref (p))
45 #define g_type_plugin_unref(p)                          ((p)->vtable->plugin_unref (p))
46 #define g_type_plugin_complete_type_info(p,t,i,v)       ((p)->vtable->complete_type_info ((p), (t), (i), (v)))
47 #define g_type_plugin_complete_interface_info(p,f,t,i)  ((p)->vtable->complete_interface_info ((p), (f), (t), (i)))
48
49 typedef struct _TypeNode        TypeNode;
50 typedef struct _CommonData      CommonData;
51 typedef struct _IFaceData       IFaceData;
52 typedef struct _ClassData       ClassData;
53 typedef struct _InstanceData    InstanceData;
54 typedef union  _TypeData        TypeData;
55 typedef struct _IFaceEntry      IFaceEntry;
56 typedef struct _IFaceHolder     IFaceHolder;
57
58
59 /* --- prototypes --- */
60 static inline GTypeFundamentalInfo*     type_node_fundamental_info      (TypeNode               *node);
61 static        void                      type_data_make                  (TypeNode               *node,
62                                                                          const GTypeInfo        *info,
63                                                                          const GTypeValueTable  *value_table);
64 static inline void                      type_data_ref                   (TypeNode               *node);
65 static inline void                      type_data_unref                 (TypeNode               *node,
66                                                                          gboolean                uncached);
67 static        void                      type_data_last_unref            (GType                   type,
68                                                                          gboolean                uncached);
69
70
71 /* --- structures --- */
72 struct _TypeNode
73 {
74   GTypePlugin *plugin;
75   guint        n_children : 12;
76   guint        n_supers : 8;
77   guint        n_ifaces : 9;
78   guint        is_classed : 1;
79   guint        is_instantiatable : 1;
80   guint        is_iface : 1;
81   GType       *children;
82   TypeData    *data;
83   GQuark       qname;
84   GData       *static_gdata;
85   union {
86     IFaceEntry  *iface_entries;
87     IFaceHolder *iface_conformants;
88   } private;
89   GType        supers[1]; /* flexible array */
90 };
91 #define SIZEOF_BASE_TYPE_NODE() (G_STRUCT_OFFSET (TypeNode, supers))
92 #define MAX_N_SUPERS    (255)
93 #define MAX_N_CHILDREN  (4095)
94 #define MAX_N_IFACES    (511)
95
96 struct _IFaceHolder
97 {
98   GType           instance_type;
99   GInterfaceInfo *info;
100   GTypePlugin    *plugin;
101   IFaceHolder    *next;
102 };
103 struct _IFaceEntry
104 {
105   GType           iface_type;
106   GTypeInterface *vtable;
107 };
108 struct _CommonData
109 {
110   guint             ref_count;
111   GTypeValueTable  *value_table;
112 };
113 struct _IFaceData
114 {
115   CommonData         common;
116   guint16            vtable_size;
117   GBaseInitFunc      vtable_init_base;
118   GBaseFinalizeFunc  vtable_finalize_base;
119 };
120 struct _ClassData
121 {
122   CommonData         common;
123   guint16            class_size;
124   GBaseInitFunc      class_init_base;
125   GBaseFinalizeFunc  class_finalize_base;
126   GClassInitFunc     class_init;
127   GClassFinalizeFunc class_finalize;
128   gconstpointer      class_data;
129   gpointer           class;
130 };
131 struct _InstanceData
132 {
133   CommonData         common;
134   guint16            class_size;
135   GBaseInitFunc      class_init_base;
136   GBaseFinalizeFunc  class_finalize_base;
137   GClassInitFunc     class_init;
138   GClassFinalizeFunc class_finalize;
139   gconstpointer      class_data;
140   gpointer           class;
141   guint16            instance_size;
142   guint16            n_preallocs;
143   GInstanceInitFunc  instance_init;
144   GMemChunk        *mem_chunk;
145 };
146 union _TypeData
147 {
148   CommonData         common;
149   IFaceData          iface;
150   ClassData          class;
151   InstanceData       instance;
152 };
153 typedef struct {
154   gpointer            cache_data;
155   GTypeClassCacheFunc cache_func;
156 } ClassCacheFunc;
157
158
159 /* --- variables --- */
160 static guint           n_class_cache_funcs = 0;
161 static ClassCacheFunc *class_cache_funcs = NULL;
162
163
164 /* --- externs --- */
165 const char *g_log_domain_gobject = "GLib-Object";
166 GOBJECT_VAR GType _g_type_fundamental_last = 0;
167
168
169 /* --- type nodes --- */
170 static GHashTable       *g_type_nodes_ht = NULL;
171 static GType            *g_branch_seqnos = NULL;
172 static TypeNode       ***g_type_nodes = NULL;
173
174 static inline TypeNode*
175 LOOKUP_TYPE_NODE (register GType utype)
176 {
177   register GType ftype = G_TYPE_FUNDAMENTAL (utype);
178   register GType b_seqno = G_TYPE_BRANCH_SEQNO (utype);
179
180   if (ftype < G_TYPE_FUNDAMENTAL_LAST && b_seqno < g_branch_seqnos[ftype])
181     return g_type_nodes[ftype][b_seqno];
182   else
183     return NULL;
184 }
185 #define NODE_TYPE(node)         (node->supers[0])
186 #define NODE_PARENT_TYPE(node)  (node->supers[1])
187 #define NODE_NAME(node)         (g_quark_to_string (node->qname))
188
189 static TypeNode*
190 type_node_any_new (TypeNode    *pnode,
191                    GType        ftype,
192                    const gchar *name,
193                    GTypePlugin *plugin,
194                    GTypeFlags   type_flags)
195 {
196   guint branch_last, n_supers = pnode ? pnode->n_supers + 1 : 0;
197   GType type;
198   TypeNode *node;
199   guint i, node_size = 0;
200
201   branch_last = g_branch_seqnos[ftype]++;
202   type = G_TYPE_DERIVE_ID (ftype, branch_last);
203   if (!branch_last || g_bit_storage (branch_last - 1) < g_bit_storage (g_branch_seqnos[ftype] - 1))
204     g_type_nodes[ftype] = g_renew (TypeNode*, g_type_nodes[ftype], 1 << g_bit_storage (g_branch_seqnos[ftype] - 1));
205
206   if (!pnode)
207     node_size += sizeof (GTypeFundamentalInfo);  /* fundamental type info */
208   node_size += SIZEOF_BASE_TYPE_NODE ();         /* TypeNode structure */
209   node_size += (sizeof (GType) * (1 + n_supers + 1)); /* self + ancestors + 0 for ->supers[] */
210   node = g_malloc0 (node_size);
211   if (!pnode)                                    /* fundamental type */
212     node = G_STRUCT_MEMBER_P (node, sizeof (GTypeFundamentalInfo));
213   g_type_nodes[ftype][branch_last] = node;
214
215   node->n_supers = n_supers;
216   if (!pnode)
217     {
218       node->supers[0] = type;
219       node->supers[1] = 0;
220
221       node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0;
222       node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0;
223       node->is_iface = G_TYPE_IS_INTERFACE (type);
224
225       node->n_ifaces = 0;
226       if (node->is_iface)
227         node->private.iface_conformants = NULL;
228       else
229         node->private.iface_entries = NULL;
230     }
231   else
232     {
233       node->supers[0] = type;
234       memcpy (node->supers + 1, pnode->supers, sizeof (GType) * (1 + pnode->n_supers + 1));
235
236       node->is_classed = pnode->is_classed;
237       node->is_instantiatable = pnode->is_instantiatable;
238       node->is_iface = pnode->is_iface;
239
240       if (node->is_iface)
241         {
242           node->n_ifaces = 0;
243           node->private.iface_conformants = NULL;
244         }
245       else
246         {
247           node->n_ifaces = pnode->n_ifaces;
248           node->private.iface_entries = g_memdup (pnode->private.iface_entries,
249                                                   sizeof (pnode->private.iface_entries[0]) * node->n_ifaces);
250         }
251       
252       i = pnode->n_children++;
253       pnode->children = g_renew (GType, pnode->children, pnode->n_children);
254       pnode->children[i] = type;
255     }
256
257   node->plugin = plugin;
258   node->n_children = 0;
259   node->children = NULL;
260   node->data = NULL;
261   node->qname = g_quark_from_string (name);
262   node->static_gdata = NULL;
263
264   g_hash_table_insert (g_type_nodes_ht,
265                        GUINT_TO_POINTER (node->qname),
266                        GUINT_TO_POINTER (type));
267
268   return node;
269 }
270
271 static inline GTypeFundamentalInfo*
272 type_node_fundamental_info (TypeNode *node)
273 {
274   GType ftype = G_TYPE_FUNDAMENTAL (NODE_TYPE (node));
275   
276   if (ftype != NODE_TYPE (node))
277     node = LOOKUP_TYPE_NODE (ftype);
278   
279   return node ? G_STRUCT_MEMBER_P (node, - sizeof (GTypeFundamentalInfo)) : NULL;
280 }
281
282 static TypeNode*
283 type_node_fundamental_new (GType        ftype,
284                            const gchar *name,
285                            GTypeFlags   type_flags)
286 {
287   GTypeFundamentalInfo *finfo;
288   TypeNode *node;
289   guint i, flast = G_TYPE_FUNDAMENTAL_LAST;
290   
291   g_assert (ftype == G_TYPE_FUNDAMENTAL (ftype));
292   
293   type_flags &= G_TYPE_FLAG_MASK;
294
295   _g_type_fundamental_last = MAX (_g_type_fundamental_last, ftype + 1);
296   if (G_TYPE_FUNDAMENTAL_LAST > flast)
297     {
298       g_type_nodes = g_renew (TypeNode**, g_type_nodes, G_TYPE_FUNDAMENTAL_LAST);
299       g_branch_seqnos = g_renew (GType, g_branch_seqnos, G_TYPE_FUNDAMENTAL_LAST);
300       for (i = flast; i < G_TYPE_FUNDAMENTAL_LAST; i++)
301         {
302           g_type_nodes[i] = NULL;
303           g_branch_seqnos[i] = 0;
304         }
305     }
306   g_assert (g_branch_seqnos[ftype] == 0);
307
308   node = type_node_any_new (NULL, ftype, name, NULL, type_flags);
309   finfo = type_node_fundamental_info (node);
310   finfo->type_flags = type_flags;
311
312   return node;
313 }
314
315 static TypeNode*
316 type_node_new (TypeNode    *pnode,
317                const gchar *name,
318                GTypePlugin *plugin)
319
320 {
321   g_assert (pnode);
322   g_assert (pnode->n_supers < MAX_N_SUPERS);
323   g_assert (pnode->n_children < MAX_N_CHILDREN);
324
325   return type_node_any_new (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (pnode)), name, plugin, 0);
326 }
327
328 static inline IFaceEntry*
329 type_lookup_iface_entry (TypeNode *node,
330                          TypeNode *iface)
331 {
332   if (iface->is_iface && node->n_ifaces)
333     {
334       IFaceEntry *ifaces = node->private.iface_entries - 1;
335       guint n_ifaces = node->n_ifaces;
336       GType iface_type = NODE_TYPE (iface);
337
338       do                /* FIXME: should optimize iface lookups for <= 4 */
339         {
340           guint i;
341           IFaceEntry *check;
342
343           i = (n_ifaces + 1) / 2;
344           check = ifaces + i;
345           if (iface_type == check->iface_type)
346             return check;
347           else if (iface_type > check->iface_type)
348             {
349               n_ifaces -= i;
350               ifaces = check;
351             }
352           else /* if (iface_type < check->iface_type) */
353             n_ifaces = i - 1;
354         }
355       while (n_ifaces);
356     }
357
358   return NULL;
359 }
360
361 static inline gchar*
362 type_descriptive_name (GType type)
363 {
364   if (type)
365     {
366       gchar *name = g_type_name (type);
367
368       return name ? name : "<unknown>";
369     }
370   else
371     return "<invalid>";
372 }
373
374
375 /* --- type consistency checks --- */
376 static gboolean
377 check_plugin (GTypePlugin *plugin,
378               gboolean     need_complete_type_info,
379               gboolean     need_complete_interface_info,
380               const gchar *type_name)
381 {
382   if (!plugin)
383     {
384       g_warning ("plugin handle for type `%s' is NULL",
385                  type_name);
386       return FALSE;
387     }
388   if (!plugin->vtable)
389     {
390       g_warning ("plugin for type `%s' has no function table",
391                  type_name);
392       return FALSE;
393     }
394   if (!plugin->vtable->plugin_ref)
395     {
396       g_warning ("plugin for type `%s' has no plugin_ref() implementation",
397                  type_name);
398       return FALSE;
399     }
400   if (!plugin->vtable->plugin_unref)
401     {
402       g_warning ("plugin for type `%s' has no plugin_unref() implementation",
403                  type_name);
404       return FALSE;
405     }
406   if (need_complete_type_info && !plugin->vtable->complete_type_info)
407     {
408       g_warning ("plugin for type `%s' has no complete_type_info() implementation",
409                  type_name);
410       return FALSE;
411     }
412   if (need_complete_interface_info && !plugin->vtable->complete_interface_info)
413     {
414       g_warning ("plugin for type `%s' has no complete_interface_info() implementation",
415                  type_name);
416       return FALSE;
417     }
418   return TRUE;
419 }
420
421 static gboolean
422 check_type_name (const gchar *type_name)
423 {
424   static const gchar *extra_chars = "-_+";
425   const gchar *p = type_name;
426   gboolean name_valid;
427
428   if (!type_name[0] || !type_name[1] || !type_name[2])
429     {
430       g_warning ("type name `%s' is too short", type_name);
431       return FALSE;
432     }
433   /* check the first letter */
434   name_valid = (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || p[0] == '_';
435   for (p = type_name + 1; *p; p++)
436     name_valid &= ((p[0] >= 'A' && p[0] <= 'Z') ||
437                    (p[0] >= 'a' && p[0] <= 'z') ||
438                    (p[0] >= '0' && p[0] <= '9') ||
439                    strchr (extra_chars, p[0]));
440   if (!name_valid)
441     {
442       g_warning ("type name `%s' contains invalid characters", type_name);
443       return FALSE;
444     }
445   if (g_type_from_name (type_name))
446     {
447       g_warning ("cannot register existing type `%s'", type_name);
448       return FALSE;
449     }
450
451   return TRUE;
452 }
453
454 static gboolean
455 check_derivation (GType        parent_type,
456                   const gchar *type_name)
457 {
458   TypeNode *pnode = LOOKUP_TYPE_NODE (parent_type);
459   GTypeFundamentalInfo* finfo = type_node_fundamental_info (pnode);
460   
461   if (!pnode)
462     {
463       g_warning ("cannot derive type `%s' from invalid parent type `%s'",
464                  type_name,
465                  type_descriptive_name (parent_type));
466       return FALSE;
467     }
468   /* ensure flat derivability */
469   if (!(finfo->type_flags & G_TYPE_FLAG_DERIVABLE))
470     {
471       g_warning ("cannot derive `%s' from non-derivable parent type `%s'",
472                  type_name,
473                  NODE_NAME (pnode));
474       return FALSE;
475     }
476   /* ensure deep derivability */
477   if (parent_type != G_TYPE_FUNDAMENTAL (parent_type) &&
478       !(finfo->type_flags & G_TYPE_FLAG_DEEP_DERIVABLE))
479     {
480       g_warning ("cannot derive `%s' from non-fundamental parent type `%s'",
481                  type_name,
482                  NODE_NAME (pnode));
483       return FALSE;
484     }
485   
486   return TRUE;
487 }
488
489 static gboolean
490 check_value_table (const gchar           *type_name,
491                    const GTypeValueTable *value_table)
492 {
493   if (!value_table)
494     return FALSE;
495   else if (value_table->value_init == NULL)
496     {
497       if (value_table->value_free || value_table->value_copy ||
498           value_table->collect_type || value_table->collect_value ||
499           value_table->lcopy_type || value_table->lcopy_value)
500         g_warning ("cannot handle uninitializable values of type `%s'",
501                    type_name);
502
503       return FALSE;
504     }
505   else /* value_table->value_init != NULL */
506     {
507       if (!value_table->value_free)
508         {
509           /* +++ optional +++
510            * g_warning ("missing `value_free()' for type `%s'", type_name);
511            * return FALSE;
512            */
513         }
514       if (!value_table->value_copy)
515         {
516           g_warning ("missing `value_copy()' for type `%s'", type_name);
517           return FALSE;
518         }
519       if ((value_table->collect_type || value_table->collect_value) &&
520           (!value_table->collect_type || !value_table->collect_value))
521         {
522           g_warning ("one of `collect_type' and `collect_value()' is unspecified for type `%s'",
523                      type_name);
524           return FALSE;
525         }
526       if ((value_table->lcopy_type || value_table->lcopy_value) &&
527           (!value_table->lcopy_type || !value_table->lcopy_value))
528         {
529           g_warning ("one of `lcopy_type' and `lcopy_value()' is unspecified for type `%s'",
530                      type_name);
531           return FALSE;
532         }
533     }
534
535   return TRUE;
536 }
537
538 static gboolean
539 check_type_info (TypeNode        *pnode,
540                  GType            ftype,
541                  const gchar     *type_name,
542                  const GTypeInfo *info)
543 {
544   GTypeFundamentalInfo *finfo = type_node_fundamental_info (LOOKUP_TYPE_NODE (ftype));
545   gboolean is_interface = G_TYPE_IS_INTERFACE (ftype);
546
547   /* check instance members */
548   if (!(finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
549       (info->instance_size || info->n_preallocs || info->instance_init))
550     {
551       if (pnode)
552         g_warning ("cannot instantiate `%s', derived from non-instantiatable parent type `%s'",
553                    type_name,
554                    NODE_NAME (pnode));
555       else
556         g_warning ("cannot instantiate `%s' as non-instantiatable fundamental",
557                    type_name);
558       return FALSE;
559     }
560   /* check class & interface members */
561   if (!(finfo->type_flags & G_TYPE_FLAG_CLASSED) &&
562       (info->class_init || info->class_finalize || info->class_data ||
563        (!is_interface && (info->class_size || info->base_init || info->base_finalize))))
564     {
565       if (pnode)
566         g_warning ("cannot create class for `%s', derived from non-classed parent type `%s'",
567                    type_name,
568                    NODE_NAME (pnode));
569       else
570         g_warning ("cannot create class for `%s' as non-classed fundamental",
571                    type_name);
572       return FALSE;
573     }
574   /* check interface size */
575   if (is_interface && info->class_size < sizeof (GTypeInterface))
576     {
577       g_warning ("specified interface size for type `%s' is smaller than `GTypeInterface' size",
578                  type_name);
579       return FALSE;
580     }
581   /* check class size */
582   if (finfo->type_flags & G_TYPE_FLAG_CLASSED)
583     {
584       if (info->class_size < sizeof (GTypeClass))
585         {
586           g_warning ("specified class size for type `%s' is smaller than `GTypeClass' size",
587                      type_name);
588           return FALSE;
589         }
590       if (pnode && info->class_size < pnode->data->class.class_size)
591         {
592           g_warning ("specified class size for type `%s' is smaller "
593                      "than the parent type's `%s' class size",
594                      type_name,
595                      NODE_NAME (pnode));
596           return FALSE;
597         }
598     }
599   /* check instance size */
600   if (finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE)
601     {
602       if (info->instance_size < sizeof (GTypeInstance))
603         {
604           g_warning ("specified instance size for type `%s' is smaller than `GTypeInstance' size",
605                      type_name);
606           return FALSE;
607         }
608       if (pnode && info->instance_size < pnode->data->instance.instance_size)
609         {
610           g_warning ("specified instance size for type `%s' is smaller "
611                      "than the parent type's `%s' instance size",
612                      type_name,
613                      NODE_NAME (pnode));
614           return FALSE;
615         }
616     }
617
618   return TRUE;
619 }
620
621 static TypeNode*
622 find_conforming_type (TypeNode *pnode,
623                       TypeNode *iface)
624 {
625   TypeNode *node = NULL;
626   guint i;
627
628   if (type_lookup_iface_entry (pnode, iface))
629     return pnode;
630
631   for (i = 0; i < pnode->n_children && !node; i++)
632     node = find_conforming_type (LOOKUP_TYPE_NODE (pnode->children[i]), iface);
633
634   return node;
635 }
636
637 static gboolean
638 check_add_interface (GType instance_type,
639                      GType iface_type)
640 {
641   TypeNode *node = LOOKUP_TYPE_NODE (instance_type);
642   TypeNode *iface = LOOKUP_TYPE_NODE (iface_type);
643   TypeNode *tnode;
644
645   if (!node || !node->is_instantiatable)
646     {
647       g_warning ("cannot add interfaces to invalid (non-instantiatable) type `%s'",
648                  type_descriptive_name (instance_type));
649       return FALSE;
650     }
651   if (!iface || !iface->is_iface)
652     {
653       g_warning ("cannot add invalid (non-interface) type `%s' to type `%s'",
654                  type_descriptive_name (iface_type),
655                  NODE_NAME (node));
656       return FALSE;
657     }
658   tnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (iface));
659   if (NODE_PARENT_TYPE (tnode) && !type_lookup_iface_entry (node, tnode))
660     {
661       g_warning ("cannot add sub-interface `%s' to type `%s' which does not conform to super-interface `%s'",
662                  NODE_NAME (iface),
663                  NODE_NAME (node),
664                  NODE_NAME (tnode));
665       return FALSE;
666     }
667   tnode = find_conforming_type (node, iface);
668   if (tnode)
669     {
670       g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface",
671                  NODE_NAME (iface),
672                  NODE_NAME (node),
673                  NODE_NAME (tnode));
674       return FALSE;
675     }
676
677   return TRUE;
678 }
679
680 static gboolean
681 check_interface_info (TypeNode             *iface,
682                       GType                 instance_type,
683                       const GInterfaceInfo *info)
684 {
685   if ((info->interface_finalize || info->interface_data) && !info->interface_init)
686     {
687       g_warning ("interface type `%s' for type `%s' comes without initializer",
688                  NODE_NAME (iface),
689                  type_descriptive_name (instance_type));
690       return FALSE;
691     }
692
693   return TRUE;
694 }
695
696
697 /* --- type info (type node data) --- */
698 static void
699 type_data_make (TypeNode              *node,
700                 const GTypeInfo       *info,
701                 const GTypeValueTable *value_table)
702 {
703   TypeData *data;
704   GTypeValueTable *vtable = NULL;
705   guint vtable_size = 0;
706   
707   g_assert (node->data == NULL && info != NULL);
708   
709   if (!value_table)
710     {
711       TypeNode *pnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (node));
712       
713       if (pnode)
714         vtable = pnode->data->common.value_table;
715       else
716         {
717           static const GTypeValueTable zero_vtable = { NULL, };
718           
719           value_table = &zero_vtable;
720         }
721     }
722   if (value_table)
723     vtable_size = sizeof (GTypeValueTable);
724   
725   if (node->is_instantiatable) /* carefull, is_instantiatable is also is_classed */
726     {
727       data = g_malloc0 (sizeof (InstanceData) + vtable_size);
728       if (vtable_size)
729         vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData));
730       data->instance.class_size = info->class_size;
731       data->instance.class_init_base = info->base_init;
732       data->instance.class_finalize_base = info->base_finalize;
733       data->instance.class_init = info->class_init;
734       data->instance.class_finalize = info->class_finalize;
735       data->instance.class_data = info->class_data;
736       data->instance.class = NULL;
737       data->instance.instance_size = info->instance_size;
738       data->instance.n_preallocs = MIN (info->n_preallocs, 1024);
739 #ifdef FIXME_DISABLE_PREALLOCATIONS
740       data->instance.n_preallocs = 0;
741 #endif
742       data->instance.instance_init = info->instance_init;
743       data->instance.mem_chunk = NULL;
744     }
745   else if (node->is_classed) /* only classed */
746     {
747       data = g_malloc0 (sizeof (ClassData) + vtable_size);
748       if (vtable_size)
749         vtable = G_STRUCT_MEMBER_P (data, sizeof (ClassData));
750       data->class.class_size = info->class_size;
751       data->class.class_init_base = info->base_init;
752       data->class.class_finalize_base = info->base_finalize;
753       data->class.class_init = info->class_init;
754       data->class.class_finalize = info->class_finalize;
755       data->class.class_data = info->class_data;
756       data->class.class = NULL;
757     }
758   else if (node->is_iface)
759     {
760       data = g_malloc0 (sizeof (IFaceData) + vtable_size);
761       if (vtable_size)
762         vtable = G_STRUCT_MEMBER_P (data, sizeof (IFaceData));
763       data->iface.vtable_size = info->class_size;
764       data->iface.vtable_init_base = info->base_init;
765       data->iface.vtable_finalize_base = info->base_finalize;
766     }
767   else
768     {
769       data = g_malloc0 (sizeof (CommonData) + vtable_size);
770       if (vtable_size)
771         vtable = G_STRUCT_MEMBER_P (data, sizeof (CommonData));
772     }
773   
774   node->data = data;
775   node->data->common.ref_count = 1;
776   
777   if (vtable_size)
778     *vtable = *value_table;
779   node->data->common.value_table = vtable;
780
781   g_assert (node->data->common.value_table != NULL); // FIXME: paranoid
782 }
783
784 static inline void
785 type_data_ref (TypeNode *node)
786 {
787   if (!node->data)
788     {
789       TypeNode *pnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (node));
790       GTypeInfo tmp_info;
791       GTypeValueTable tmp_value_table;
792       
793       g_assert (node->plugin != NULL);
794       
795       if (pnode)
796         type_data_ref (pnode);
797       
798       memset (&tmp_info, 0, sizeof (tmp_info));
799       memset (&tmp_value_table, 0, sizeof (tmp_value_table));
800       g_type_plugin_ref (node->plugin);
801       g_type_plugin_complete_type_info (node->plugin, NODE_TYPE (node), &tmp_info, &tmp_value_table);
802       check_type_info (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), NODE_NAME (node), &tmp_info);
803       type_data_make (node, &tmp_info,
804                       check_value_table (NODE_NAME (node), &tmp_value_table) ? &tmp_value_table : NULL);
805     }
806   else
807     {
808       g_assert (node->data->common.ref_count > 0);
809
810       node->data->common.ref_count += 1;
811     }
812 }
813
814 static inline void
815 type_data_unref (TypeNode *node,
816                  gboolean  uncached)
817 {
818   g_assert (node->data && node->data->common.ref_count);
819
820   if (node->data->common.ref_count > 1)
821     node->data->common.ref_count -= 1;
822   else
823     {
824       if (!node->plugin)
825         {
826           g_warning ("static type `%s' unreferenced too often",
827                      NODE_NAME (node));
828           return;
829         }
830
831       type_data_last_unref (NODE_TYPE (node), uncached);
832     }
833 }
834
835 static void
836 type_node_add_iface_entry (TypeNode *node,
837                            GType     iface_type)
838 {
839   IFaceEntry *entries;
840   guint i;
841
842   g_assert (node->is_instantiatable && node->n_ifaces < MAX_N_IFACES);
843
844   node->n_ifaces++;
845   node->private.iface_entries = g_renew (IFaceEntry, node->private.iface_entries, node->n_ifaces);
846   entries = node->private.iface_entries;
847   for (i = 0; i < node->n_ifaces - 1; i++)
848     if (entries[i].iface_type > iface_type)
849       break;
850   g_memmove (entries + i + 1, entries + i, sizeof (entries[0]) * (node->n_ifaces - i - 1));
851   entries[i].iface_type = iface_type;
852   entries[i].vtable = NULL;
853
854   for (i = 0; i < node->n_children; i++)
855     type_node_add_iface_entry (LOOKUP_TYPE_NODE (node->children[i]), iface_type);
856 }
857
858 static void
859 type_add_interface (TypeNode       *node,
860                     TypeNode       *iface,
861                     GInterfaceInfo *info,
862                     GTypePlugin    *plugin)
863 {
864   IFaceHolder *iholder = g_new0 (IFaceHolder, 1);
865   
866   /* we must not call any functions of GInterfaceInfo from within here, since
867    * we got most probably called from _within_ a type registration function
868    */
869   g_assert (node->is_instantiatable && iface->is_iface && ((info && !plugin) || (!info && plugin)));
870   
871   iholder->next = iface->private.iface_conformants;
872   iface->private.iface_conformants = iholder;
873   iholder->instance_type = NODE_TYPE (node);
874   iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
875   iholder->plugin = plugin;
876
877   type_node_add_iface_entry (node, NODE_TYPE (iface));
878 }
879
880 static IFaceHolder*
881 type_iface_retrive_holder_info (TypeNode *iface,
882                                 GType     instance_type)
883 {
884   IFaceHolder *iholder = iface->private.iface_conformants;
885
886   g_assert (iface->is_iface);
887
888   while (iholder->instance_type != instance_type)
889     iholder = iholder->next;
890
891   if (!iholder->info)
892     {
893       GInterfaceInfo tmp_info;
894       
895       g_assert (iholder->plugin != NULL);
896       
897       type_data_ref (iface);
898
899       memset (&tmp_info, 0, sizeof (tmp_info));
900       g_type_plugin_ref (iholder->plugin);
901       g_type_plugin_complete_interface_info (iholder->plugin, NODE_TYPE (iface), instance_type, &tmp_info);
902       check_interface_info (iface, instance_type, &tmp_info);
903       iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
904     }
905   
906   return iholder;
907 }
908
909 static void
910 type_iface_blow_holder_info (TypeNode *iface,
911                              GType     instance_type)
912 {
913   IFaceHolder *iholder = iface->private.iface_conformants;
914
915   g_assert (iface->is_iface);
916
917   while (iholder->instance_type != instance_type)
918     iholder = iholder->next;
919
920   if (iholder->info && iholder->plugin)
921     {
922       g_free (iholder->info);
923       iholder->info = NULL;
924       g_type_plugin_unref (iholder->plugin);
925
926       type_data_unref (iface, FALSE);
927     }
928 }
929
930
931 /* --- type structure creation/destruction --- */
932 GTypeInstance*
933 g_type_create_instance (GType type)
934 {
935   TypeNode *node = LOOKUP_TYPE_NODE (type);
936   GTypeInstance *instance;
937   GTypeClass *class;
938   guint i;
939   
940   if (!node || !node->is_instantiatable)
941     {
942       g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
943                  type_descriptive_name (type));
944       return NULL;
945     }
946   
947   class = g_type_class_ref (type);
948   
949   if (node->data->instance.n_preallocs)
950     {
951       if (!node->data->instance.mem_chunk)
952         node->data->instance.mem_chunk = g_mem_chunk_new (NODE_NAME (node),
953                                                           node->data->instance.instance_size,
954                                                           (node->data->instance.instance_size *
955                                                            node->data->instance.n_preallocs),
956                                                           G_ALLOC_AND_FREE);
957       instance = g_chunk_new0 (GTypeInstance, node->data->instance.mem_chunk);
958     }
959   else
960     instance = g_malloc0 (node->data->instance.instance_size);
961   
962   for (i = node->n_supers; i > 0; i--)
963     {
964       TypeNode *pnode = LOOKUP_TYPE_NODE (node->supers[i]);
965       
966       if (pnode->data->instance.instance_init)
967         {
968           instance->g_class = pnode->data->instance.class;
969           pnode->data->instance.instance_init (instance, class);
970         }
971     }
972   instance->g_class = class;
973   if (node->data->instance.instance_init)
974     node->data->instance.instance_init (instance, class);
975
976   return instance;
977 }
978
979 void
980 g_type_free_instance (GTypeInstance *instance)
981 {
982   TypeNode *node;
983   GTypeClass *class;
984
985   g_return_if_fail (instance != NULL && instance->g_class != NULL);
986
987   class = instance->g_class;
988   node = LOOKUP_TYPE_NODE (class->g_type);
989   if (!node || !node->is_instantiatable || !node->data || node->data->class.class != (gpointer) class)
990     {
991       g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
992                  type_descriptive_name (class->g_type));
993       return;
994     }
995
996   instance->g_class = NULL;
997   if (node->data->instance.n_preallocs)
998     g_chunk_free (instance, node->data->instance.mem_chunk);
999   else
1000     g_free (instance);
1001
1002   g_type_class_unref (class);
1003 }
1004
1005 static void
1006 type_propagate_iface_vtable (TypeNode       *pnode,
1007                              TypeNode       *iface,
1008                              GTypeInterface *vtable)
1009 {
1010   IFaceEntry *entry = type_lookup_iface_entry (pnode, iface);
1011   guint i;
1012
1013   entry->vtable = vtable;
1014   for (i = 0; i < pnode->n_children; i++)
1015     {
1016       TypeNode *node = LOOKUP_TYPE_NODE (pnode->children[i]);
1017
1018       type_propagate_iface_vtable (node, iface, vtable);
1019     }
1020 }
1021
1022 static void
1023 type_iface_vtable_init (TypeNode       *iface,
1024                         TypeNode       *node)
1025 {
1026   IFaceEntry *entry = type_lookup_iface_entry (node, iface);
1027   IFaceHolder *iholder = type_iface_retrive_holder_info (iface, NODE_TYPE (node));
1028   GTypeInterface *vtable;
1029   
1030   g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info);
1031
1032   vtable = g_malloc0 (iface->data->iface.vtable_size);
1033   type_propagate_iface_vtable (node, iface, vtable);
1034   vtable->g_type = NODE_TYPE (iface);
1035   vtable->g_instance_type = NODE_TYPE (node);
1036
1037   if (iface->data->iface.vtable_init_base)
1038     iface->data->iface.vtable_init_base (vtable);
1039   if (iholder->info->interface_init)
1040     iholder->info->interface_init (vtable, iholder->info->interface_data);
1041 }
1042
1043 static void
1044 type_iface_vtable_finalize (TypeNode       *iface,
1045                             TypeNode       *node,
1046                             GTypeInterface *vtable)
1047 {
1048   IFaceEntry *entry = type_lookup_iface_entry (node, iface);
1049   IFaceHolder *iholder = iface->private.iface_conformants;
1050
1051   g_assert (entry && entry->vtable == vtable);
1052
1053   while (iholder->instance_type != NODE_TYPE (node))
1054     iholder = iholder->next;
1055   g_assert (iholder && iholder->info);
1056
1057   type_propagate_iface_vtable (node, iface, NULL);
1058   if (iholder->info->interface_finalize)
1059     iholder->info->interface_finalize (vtable, iholder->info->interface_data);
1060   if (iface->data->iface.vtable_finalize_base)
1061     iface->data->iface.vtable_finalize_base (vtable);
1062   
1063   vtable->g_type = 0;
1064   vtable->g_instance_type = 0;
1065   g_free (vtable);
1066
1067   type_iface_blow_holder_info (iface, NODE_TYPE (node));
1068 }
1069
1070 static void
1071 type_class_init (TypeNode   *node,
1072                  GTypeClass *pclass)
1073 {
1074   GSList *slist, *init_slist = NULL;
1075   GTypeClass *class;
1076   IFaceEntry *entry;
1077   TypeNode *bnode;
1078   guint i;
1079   
1080   g_assert (node->is_classed && node->data &&
1081             node->data->class.class_size &&
1082             !node->data->class.class);
1083   
1084   class = g_malloc0 (node->data->class.class_size);
1085   node->data->class.class = class;
1086   
1087   if (pclass)
1088     {
1089       TypeNode *pnode = LOOKUP_TYPE_NODE (pclass->g_type);
1090       
1091       memcpy (class, pclass, pnode->data->class.class_size);
1092     }
1093   
1094   class->g_type = NODE_TYPE (node);
1095   
1096   /* stack all base class initialization functions, so we
1097    * call them in ascending order.
1098    */
1099   for (bnode = node; bnode; bnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (bnode)))
1100     if (bnode->data->class.class_init_base)
1101       init_slist = g_slist_prepend (init_slist, bnode->data->class.class_init_base);
1102   for (slist = init_slist; slist; slist = slist->next)
1103     {
1104       GBaseInitFunc class_init_base = slist->data;
1105       
1106       class_init_base (class);
1107     }
1108   g_slist_free (init_slist);
1109   
1110   if (node->data->class.class_init)
1111     node->data->class.class_init (class, (gpointer) node->data->class.class_data);
1112
1113   /* ok, we got the class done, now initialize all interfaces */
1114   for (entry = NULL, i = 0; i < node->n_ifaces; i++)
1115     if (!node->private.iface_entries[i].vtable)
1116       entry = node->private.iface_entries + i;
1117   while (entry)
1118     {
1119       type_iface_vtable_init (LOOKUP_TYPE_NODE (entry->iface_type), node);
1120       
1121       for (entry = NULL, i = 0; i < node->n_ifaces; i++)
1122         if (!node->private.iface_entries[i].vtable)
1123           entry = node->private.iface_entries + i;
1124     }
1125 }
1126
1127 static void
1128 type_data_finalize_class_ifaces (TypeNode *node)
1129 {
1130   IFaceEntry *entry;
1131   guint i;
1132   
1133   g_assert (node->is_instantiatable && node->data && node->data->class.class && node->data->common.ref_count == 0);
1134   
1135   g_message ("finalizing interfaces for %sClass `%s'",
1136              type_descriptive_name (G_TYPE_FUNDAMENTAL (NODE_TYPE (node))),
1137              type_descriptive_name (NODE_TYPE (node)));
1138   
1139   for (entry = NULL, i = 0; i < node->n_ifaces; i++)
1140     if (node->private.iface_entries[i].vtable &&
1141         node->private.iface_entries[i].vtable->g_instance_type == NODE_TYPE (node))
1142       entry = node->private.iface_entries + i;
1143   while (entry)
1144     {
1145       type_iface_vtable_finalize (LOOKUP_TYPE_NODE (entry->iface_type), node, entry->vtable);
1146       
1147       for (entry = NULL, i = 0; i < node->n_ifaces; i++)
1148         if (node->private.iface_entries[i].vtable &&
1149             node->private.iface_entries[i].vtable->g_instance_type == NODE_TYPE (node))
1150           entry = node->private.iface_entries + i;
1151     }
1152 }
1153
1154 static void
1155 type_data_finalize_class (TypeNode  *node,
1156                           ClassData *cdata)
1157 {
1158   GTypeClass *class = cdata->class;
1159   TypeNode *bnode;
1160   
1161   g_assert (cdata->class && cdata->common.ref_count == 0);
1162   
1163   g_message ("finalizing %sClass `%s'",
1164              type_descriptive_name (G_TYPE_FUNDAMENTAL (NODE_TYPE (node))),
1165              type_descriptive_name (NODE_TYPE (node)));
1166
1167   if (cdata->class_finalize)
1168     cdata->class_finalize (class, (gpointer) cdata->class_data);
1169   
1170   /* call all base class destruction functions in descending order
1171    */
1172   if (cdata->class_finalize_base)
1173     cdata->class_finalize_base (class);
1174   for (bnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (node)); bnode; bnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (bnode)))
1175     if (bnode->data->class.class_finalize_base)
1176       bnode->data->class.class_finalize_base (class);
1177   
1178   class->g_type = 0;
1179   g_free (cdata->class);
1180 }
1181
1182 static void
1183 type_data_last_unref (GType    type,
1184                       gboolean uncached)
1185 {
1186   TypeNode *node = LOOKUP_TYPE_NODE (type);
1187
1188   g_return_if_fail (node != NULL && node->plugin != NULL);
1189   
1190   if (!node->data || node->data->common.ref_count == 0)
1191     {
1192       g_warning ("cannot drop last reference to unreferenced type `%s'",
1193                  type_descriptive_name (type));
1194       return;
1195     }
1196
1197   if (node->is_classed && node->data && node->data->class.class)
1198     {
1199       guint i;
1200
1201       for (i = 0; i < n_class_cache_funcs; i++)
1202         if (class_cache_funcs[i].cache_func (class_cache_funcs[i].cache_data, node->data->class.class))
1203           break;
1204     }
1205
1206   if (node->data->common.ref_count > 1) /* may have been re-referenced meanwhile */
1207     node->data->common.ref_count -= 1;
1208   else
1209     {
1210       GType ptype = NODE_PARENT_TYPE (node);
1211       TypeData *tdata;
1212       
1213       node->data->common.ref_count = 0;
1214       
1215       if (node->is_instantiatable && node->data->instance.mem_chunk)
1216         {
1217           g_mem_chunk_destroy (node->data->instance.mem_chunk);
1218           node->data->instance.mem_chunk = NULL;
1219         }
1220       
1221       tdata = node->data;
1222       if (node->is_classed && tdata->class.class)
1223         {
1224           if (node->n_ifaces)
1225             type_data_finalize_class_ifaces (node);
1226           node->data = NULL;
1227           type_data_finalize_class (node, &tdata->class);
1228         }
1229       else
1230         node->data = NULL;
1231
1232       g_free (tdata);
1233       
1234       if (ptype)
1235         type_data_unref (LOOKUP_TYPE_NODE (ptype), FALSE);
1236       g_type_plugin_unref (node->plugin);
1237     }
1238 }
1239
1240 void
1241 g_type_add_class_cache_func (gpointer            cache_data,
1242                              GTypeClassCacheFunc cache_func)
1243 {
1244   guint i;
1245
1246   g_return_if_fail (cache_func != NULL);
1247
1248   i = n_class_cache_funcs++;
1249   class_cache_funcs = g_renew (ClassCacheFunc, class_cache_funcs, n_class_cache_funcs);
1250   class_cache_funcs[i].cache_data = cache_data;
1251   class_cache_funcs[i].cache_func = cache_func;
1252 }
1253
1254 void
1255 g_type_remove_class_cache_func (gpointer            cache_data,
1256                                 GTypeClassCacheFunc cache_func)
1257 {
1258   guint i;
1259
1260   g_return_if_fail (cache_func != NULL);
1261
1262   for (i = 0; i < n_class_cache_funcs; i++)
1263     if (class_cache_funcs[i].cache_data == cache_data &&
1264         class_cache_funcs[i].cache_func == cache_func)
1265       {
1266         n_class_cache_funcs--;
1267         g_memmove (class_cache_funcs + i,
1268                    class_cache_funcs + i + 1,
1269                    sizeof (class_cache_funcs[0]) * (n_class_cache_funcs - i));
1270         class_cache_funcs = g_renew (ClassCacheFunc, class_cache_funcs, n_class_cache_funcs);
1271
1272         return;
1273       }
1274
1275   g_warning (G_STRLOC ": cannot remove unregistered class cache func %p with data %p",
1276              cache_func, cache_data);
1277 }
1278
1279
1280 /* --- type registration --- */
1281 GType
1282 g_type_register_fundamental (GType                       type_id,
1283                              const gchar                *type_name,
1284                              const GTypeInfo            *info,
1285                              const GTypeFundamentalInfo *finfo)
1286 {
1287   GTypeFundamentalInfo *node_finfo;
1288   TypeNode *node;
1289
1290   g_return_val_if_fail (type_id > 0, 0);
1291   g_return_val_if_fail (type_name != NULL, 0);
1292   g_return_val_if_fail (info != NULL, 0);
1293   g_return_val_if_fail (finfo != NULL, 0);
1294
1295   if (!check_type_name (type_name))
1296     return 0;
1297   if (G_TYPE_FUNDAMENTAL (type_id) != type_id)
1298     {
1299       g_warning ("cannot register fundamental type `%s' with non-fundamental id (%u)",
1300                  type_name,
1301                  type_id);
1302       return 0;
1303     }
1304   if (LOOKUP_TYPE_NODE (type_id))
1305     {
1306       g_warning ("cannot register existing fundamental type `%s' (as `%s')",
1307                  type_descriptive_name (type_id),
1308                  type_name);
1309       return 0;
1310     }
1311   if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
1312       !(finfo->type_flags & G_TYPE_FLAG_CLASSED))
1313     {
1314       g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
1315                  type_name);
1316       return 0;
1317     }
1318
1319   node = type_node_fundamental_new (type_id, type_name, finfo->type_flags);
1320   node_finfo = type_node_fundamental_info (node);
1321
1322   if (!check_type_info (NULL, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), type_name, info))
1323     return NODE_TYPE (node);
1324   type_data_make (node, info,
1325                   check_value_table (type_name, info->value_table) ? info->value_table : NULL);
1326
1327   return NODE_TYPE (node);
1328 }
1329
1330 GType
1331 g_type_register_static (GType            parent_type,
1332                         const gchar     *type_name,
1333                         const GTypeInfo *info)
1334 {
1335   TypeNode *pnode, *node;
1336   GType type;
1337   
1338   g_return_val_if_fail (parent_type > 0, 0);
1339   g_return_val_if_fail (type_name != NULL, 0);
1340   g_return_val_if_fail (info != NULL, 0);
1341   
1342   if (!check_type_name (type_name))
1343     return 0;
1344   if (!check_derivation (parent_type, type_name))
1345     return 0;
1346
1347   pnode = LOOKUP_TYPE_NODE (parent_type);
1348   type_data_ref (pnode);
1349
1350   if (!check_type_info (pnode, G_TYPE_FUNDAMENTAL (parent_type), type_name, info))
1351     return 0;
1352   if (info->class_finalize)
1353     {
1354       g_warning ("class destructor specified for static type `%s'",
1355                  type_name);
1356       return 0;
1357     }
1358
1359   node = type_node_new (pnode, type_name, NULL);
1360   type = NODE_TYPE (node);
1361   type_data_make (node, info,
1362                   check_value_table (type_name, info->value_table) ? info->value_table : NULL);
1363
1364   return type;
1365 }
1366
1367 GType
1368 g_type_register_dynamic (GType        parent_type,
1369                          const gchar *type_name,
1370                          GTypePlugin *plugin)
1371 {
1372   TypeNode *pnode, *node;
1373   GType type;
1374
1375   g_return_val_if_fail (parent_type > 0, 0);
1376   g_return_val_if_fail (type_name != NULL, 0);
1377   g_return_val_if_fail (plugin != NULL, 0);
1378
1379   if (!check_type_name (type_name))
1380     return 0;
1381   if (!check_derivation (parent_type, type_name))
1382     return 0;
1383   if (!check_plugin (plugin, TRUE, FALSE, type_name))
1384     return 0;
1385   pnode = LOOKUP_TYPE_NODE (parent_type);
1386
1387   node = type_node_new (pnode, type_name, plugin);
1388   type = NODE_TYPE (node);
1389
1390   return type;
1391 }
1392
1393 void
1394 g_type_add_interface_static (GType           instance_type,
1395                              GType           interface_type,
1396                              GInterfaceInfo *info)
1397 {
1398   TypeNode *node;
1399   TypeNode *iface;
1400   
1401   g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
1402   g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
1403
1404   if (!check_add_interface (instance_type, interface_type))
1405     return;
1406   node = LOOKUP_TYPE_NODE (instance_type);
1407   iface = LOOKUP_TYPE_NODE (interface_type);
1408   if (!check_interface_info (iface, NODE_TYPE (node), info))
1409     return;
1410   type_add_interface (node, iface, info, NULL);
1411 }
1412
1413 void
1414 g_type_add_interface_dynamic (GType        instance_type,
1415                               GType        interface_type,
1416                               GTypePlugin *plugin)
1417 {
1418   TypeNode *node;
1419   TypeNode *iface;
1420   
1421   g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
1422   g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
1423
1424   if (!check_add_interface (instance_type, interface_type))
1425     return;
1426   node = LOOKUP_TYPE_NODE (instance_type);
1427   iface = LOOKUP_TYPE_NODE (interface_type);
1428   if (!check_plugin (plugin, FALSE, TRUE, NODE_NAME (node)))
1429     return;
1430   type_add_interface (node, iface, NULL, plugin);
1431 }
1432
1433
1434 /* --- public API functions --- */
1435 gpointer
1436 g_type_class_ref (GType type)
1437 {
1438   TypeNode *node = LOOKUP_TYPE_NODE (type);
1439
1440   /* optimize for common code path
1441    */
1442   if (node && node->is_classed && node->data &&
1443       node->data->class.class && node->data->common.ref_count > 0)
1444     {
1445       type_data_ref (node);
1446
1447       return node->data->class.class;
1448     }
1449
1450   if (!node || !node->is_classed ||
1451       (node->data && node->data->common.ref_count < 1))
1452     {
1453       g_warning ("cannot retrive class for invalid (unclassed) type `%s'",
1454                  type_descriptive_name (type));
1455       return NULL;
1456     }
1457
1458   type_data_ref (node);
1459
1460   if (!node->data->class.class)
1461     {
1462       GType ptype = NODE_PARENT_TYPE (node);
1463       GTypeClass *pclass = ptype ? g_type_class_ref (ptype) : NULL;
1464
1465       type_class_init (node, pclass);
1466     }
1467
1468   return node->data->class.class;
1469 }
1470
1471 void
1472 g_type_class_unref (gpointer g_class)
1473 {
1474   TypeNode *node;
1475   GTypeClass *class = g_class;
1476
1477   g_return_if_fail (g_class != NULL);
1478
1479   node = LOOKUP_TYPE_NODE (class->g_type);
1480   if (node && node->is_classed && node->data &&
1481       node->data->class.class == class && node->data->common.ref_count > 0)
1482     type_data_unref (node, FALSE);
1483   else
1484     g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
1485                type_descriptive_name (class->g_type));
1486 }
1487
1488 void
1489 g_type_class_unref_uncached (gpointer g_class)
1490 {
1491   TypeNode *node;
1492   GTypeClass *class = g_class;
1493
1494   g_return_if_fail (g_class != NULL);
1495
1496   node = LOOKUP_TYPE_NODE (class->g_type);
1497   if (node && node->is_classed && node->data &&
1498       node->data->class.class == class && node->data->common.ref_count > 0)
1499     type_data_unref (node, TRUE);
1500   else
1501     g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
1502                type_descriptive_name (class->g_type));
1503 }
1504
1505 gpointer
1506 g_type_class_peek (GType type)
1507 {
1508   TypeNode *node = LOOKUP_TYPE_NODE (type);
1509
1510   if (node && node->is_classed && node->data && node->data->class.class) /* common.ref_count _may_ be 0 */
1511     return node->data->class.class;
1512   else
1513     return NULL;
1514 }
1515
1516 gpointer
1517 g_type_class_peek_parent (gpointer g_class)
1518 {
1519   TypeNode *node;
1520
1521   g_return_val_if_fail (g_class != NULL, NULL);
1522
1523   node = LOOKUP_TYPE_NODE (G_TYPE_FROM_CLASS (g_class));
1524   if (node && node->is_classed && node->data && NODE_PARENT_TYPE (node))
1525     {
1526       node = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (node));
1527
1528       return node->data->class.class;
1529     }
1530
1531   return NULL;
1532 }
1533
1534 gpointer
1535 g_type_interface_peek (gpointer instance_class,
1536                        GType    iface_type)
1537 {
1538   TypeNode *node;
1539   TypeNode *iface;
1540   GTypeClass *class = instance_class;
1541
1542   g_return_val_if_fail (instance_class != NULL, NULL);
1543
1544   node = LOOKUP_TYPE_NODE (class->g_type);
1545   iface = LOOKUP_TYPE_NODE (iface_type);
1546   if (node && node->is_instantiatable && iface)
1547     {
1548       IFaceEntry *entry = type_lookup_iface_entry (node, iface);
1549
1550       if (entry && entry->vtable)
1551         return entry->vtable;
1552     }
1553
1554   return NULL;
1555 }
1556
1557 GTypeValueTable*
1558 g_type_value_table_peek (GType type)
1559 {
1560   TypeNode *node = LOOKUP_TYPE_NODE (type);
1561
1562   if (node && node->data && node->data->common.ref_count > 0)
1563     return node->data->common.value_table->value_init ? node->data->common.value_table : NULL;
1564   else
1565     return NULL;
1566 }
1567
1568 gchar*
1569 g_type_name (GType type)
1570 {
1571   TypeNode *node = LOOKUP_TYPE_NODE (type);
1572   
1573   return node ? NODE_NAME (node) : NULL;
1574 }
1575
1576 GQuark
1577 g_type_qname (GType type)
1578 {
1579   TypeNode *node = LOOKUP_TYPE_NODE (type);
1580
1581   return node ? node->qname : 0;
1582 }
1583
1584 GType
1585 g_type_from_name (const gchar *name)
1586 {
1587   GQuark quark;
1588   
1589   g_return_val_if_fail (name != NULL, 0);
1590   
1591   quark = g_quark_try_string (name);
1592   if (quark)
1593     {
1594       GType type = GPOINTER_TO_UINT (g_hash_table_lookup (g_type_nodes_ht, GUINT_TO_POINTER (quark)));
1595       
1596       if (type)
1597         return type;
1598     }
1599   
1600   return 0;
1601 }
1602
1603 GType
1604 g_type_parent (GType type)
1605 {
1606   TypeNode *node = LOOKUP_TYPE_NODE (type);
1607
1608   return node ? NODE_PARENT_TYPE (node) : 0;
1609 }
1610
1611 GType
1612 g_type_next_base (GType type,
1613                   GType base_type)
1614 {
1615   TypeNode *node = LOOKUP_TYPE_NODE (type);
1616   
1617   if (node)
1618     {
1619       TypeNode *base_node = LOOKUP_TYPE_NODE (base_type);
1620       
1621       if (base_node && base_node->n_supers < node->n_supers)
1622         {
1623           guint n = node->n_supers - base_node->n_supers;
1624           
1625           if (node->supers[n] == base_type)
1626             return node->supers[n - 1];
1627         }
1628     }
1629   
1630   return 0;
1631 }
1632
1633 gboolean
1634 g_type_is_a (GType type,
1635              GType is_a_type)
1636 {
1637   if (type != is_a_type)
1638     {
1639       TypeNode *node = LOOKUP_TYPE_NODE (type);
1640
1641       if (node)
1642         {
1643           TypeNode *a_node = LOOKUP_TYPE_NODE (is_a_type);
1644
1645           if (a_node && a_node->n_supers <= node->n_supers)
1646             return node->supers[node->n_supers - a_node->n_supers] == is_a_type;
1647         }
1648     }
1649   else
1650     return LOOKUP_TYPE_NODE (type) != NULL;
1651
1652   return FALSE;
1653 }
1654
1655 gboolean
1656 g_type_conforms_to (GType type,
1657                     GType iface_type)
1658 {
1659   if (type != iface_type)
1660     {
1661       TypeNode *node = LOOKUP_TYPE_NODE (type);
1662
1663       if (node)
1664         {
1665           TypeNode *iface_node = LOOKUP_TYPE_NODE (iface_type);
1666
1667           if (iface_node)
1668             {
1669               if (iface_node->is_iface && node->is_instantiatable)
1670                 return type_lookup_iface_entry (node, iface_node) != NULL;
1671               else if (iface_node->n_supers <= node->n_supers)
1672                 return node->supers[node->n_supers - iface_node->n_supers] == iface_type;
1673             }
1674         }
1675     }
1676   else
1677     {
1678       TypeNode *node = LOOKUP_TYPE_NODE (type);
1679
1680       return node && (node->is_iface || node->is_instantiatable);
1681     }
1682
1683   return FALSE;
1684 }
1685
1686 guint
1687 g_type_fundamental_branch_last (GType type)
1688 {
1689   GType ftype = G_TYPE_FUNDAMENTAL (type);
1690
1691   return ftype < G_TYPE_FUNDAMENTAL_LAST ? g_branch_seqnos[ftype] : 0;
1692 }
1693
1694 GType* /* free result */
1695 g_type_children (GType  type,
1696                  guint *n_children)
1697 {
1698   TypeNode *node = LOOKUP_TYPE_NODE (type);
1699   
1700   if (node)
1701     {
1702       GType *children = g_new (GType, node->n_children + 1);
1703       
1704       memcpy (children, node->children, sizeof (GType) * node->n_children);
1705       children[node->n_children] = 0;
1706       
1707       if (n_children)
1708         *n_children = node->n_children;
1709       
1710       return children;
1711     }
1712   else
1713     {
1714       if (n_children)
1715         *n_children = 0;
1716       
1717       return NULL;
1718     }
1719 }
1720
1721 GType* /* free result */
1722 g_type_interfaces (GType  type,
1723                    guint *n_interfaces)
1724 {
1725   TypeNode *node = LOOKUP_TYPE_NODE (type);
1726
1727   if (node && node->is_instantiatable)
1728     {
1729       GType *ifaces = g_new (GType, node->n_ifaces + 1);
1730       guint i;
1731
1732       for (i = 0; i < node->n_ifaces; i++)
1733         ifaces[i] = node->private.iface_entries[i].iface_type;
1734       ifaces[i] = 0;
1735
1736       if (n_interfaces)
1737         *n_interfaces = node->n_ifaces;
1738
1739       return ifaces;
1740     }
1741   else
1742     {
1743       if (n_interfaces)
1744         *n_interfaces = 0;
1745
1746       return NULL;
1747     }
1748 }
1749
1750 typedef struct _QData QData;
1751 struct _GData
1752 {
1753   guint  n_qdatas;
1754   QData *qdatas;
1755 };
1756 struct _QData
1757 {
1758   GQuark   quark;
1759   gpointer data;
1760 };
1761
1762 gpointer
1763 g_type_get_qdata (GType  type,
1764                   GQuark quark)
1765 {
1766   TypeNode *node = LOOKUP_TYPE_NODE (type);
1767   GData *gdata;
1768   
1769   g_return_val_if_fail (node != NULL, NULL);
1770
1771   gdata = node->static_gdata;
1772   if (quark && gdata && gdata->n_qdatas)
1773     {
1774       QData *qdatas = gdata->qdatas - 1;
1775       guint n_qdatas = gdata->n_qdatas;
1776
1777       do                /* FIXME: should optimize qdata lookups for <= 4 */
1778         {
1779           guint i;
1780           QData *check;
1781
1782           i = (n_qdatas + 1) / 2;
1783           check = qdatas + i;
1784           if (quark == check->quark)
1785             return check->data;
1786           else if (quark > check->quark)
1787             {
1788               n_qdatas -= i;
1789               qdatas = check;
1790             }
1791           else /* if (quark < check->quark) */
1792             n_qdatas = i - 1;
1793         }
1794       while (n_qdatas);
1795     }
1796
1797   return NULL;
1798 }
1799
1800 void
1801 g_type_set_qdata (GType    type,
1802                   GQuark   quark,
1803                   gpointer data)
1804 {
1805   TypeNode *node = LOOKUP_TYPE_NODE (type);
1806   GData *gdata;
1807   QData *qdata;
1808   guint i;
1809
1810   g_return_if_fail (node != NULL);
1811   g_return_if_fail (quark != 0);
1812
1813   /* setup qdata list if necessary */
1814   if (!node->static_gdata)
1815     node->static_gdata = g_new0 (GData, 1);
1816   gdata = node->static_gdata;
1817
1818   /* try resetting old data */
1819   qdata = gdata->qdatas;
1820   for (i = 0; i < gdata->n_qdatas; i++)
1821     if (qdata[i].quark == quark)
1822       {
1823         qdata[i].data = data;
1824         return;
1825       }
1826
1827   /* add new entry */
1828   gdata->n_qdatas++;
1829   gdata->qdatas = g_renew (QData, gdata->qdatas, gdata->n_qdatas);
1830   qdata = gdata->qdatas;
1831   for (i = 0; i < gdata->n_qdatas - 1; i++)
1832     if (qdata[i].quark > quark)
1833       break;
1834   g_memmove (qdata + i + 1, qdata + i, sizeof (qdata[0]) * (gdata->n_qdatas - i - 1));
1835   qdata[i].quark = quark;
1836   qdata[i].data = data;
1837 }
1838
1839
1840 /* --- implementation details --- */
1841 gboolean
1842 g_type_check_flags (GType      type,
1843                     GTypeFlags flags)
1844 {
1845   TypeNode *node = LOOKUP_TYPE_NODE (type);
1846   
1847   flags &= G_TYPE_FLAG_MASK;
1848   if (node)
1849     {
1850       GTypeFundamentalInfo *finfo = type_node_fundamental_info (node);
1851       
1852       return (finfo->type_flags & flags) != 0;
1853     }
1854   
1855   return FALSE;
1856 }
1857
1858 GTypePlugin*
1859 g_type_get_plugin (GType type)
1860 {
1861   TypeNode *node = LOOKUP_TYPE_NODE (type);
1862
1863   return node && node->plugin;
1864 }
1865
1866 gboolean
1867 g_type_instance_conforms_to (GTypeInstance *type_instance,
1868                              GType          iface_type)
1869 {
1870   return (type_instance && type_instance->g_class &&
1871           g_type_conforms_to (type_instance->g_class->g_type, iface_type));
1872 }
1873
1874 gboolean
1875 g_type_class_is_a (GTypeClass *type_class,
1876                    GType       is_a_type)
1877 {
1878   return (type_class && g_type_is_a (type_class->g_type, is_a_type));
1879 }
1880
1881 GTypeInstance*
1882 g_type_check_instance_cast (GTypeInstance *type_instance,
1883                             GType          iface_type)
1884 {
1885   if (!type_instance)
1886     {
1887       g_warning ("invalid cast from (NULL) pointer to `%s'",
1888                  type_descriptive_name (iface_type));
1889       return type_instance;
1890     }
1891   if (!type_instance->g_class)
1892     {
1893       g_warning ("invalid unclassed pointer in cast to `%s'",
1894                  type_descriptive_name (iface_type));
1895       return type_instance;
1896     }
1897   if (!G_TYPE_IS_CLASSED (type_instance->g_class->g_type))
1898     {
1899       g_warning ("invalid unclassed type `%s' in cast to `%s'",
1900                  type_descriptive_name (type_instance->g_class->g_type),
1901                  type_descriptive_name (iface_type));
1902       return type_instance;
1903     }
1904   if (!g_type_conforms_to (type_instance->g_class->g_type, iface_type))
1905     {
1906       g_warning ("invalid cast from `%s' to `%s'",
1907                  type_descriptive_name (type_instance->g_class->g_type),
1908                  type_descriptive_name (iface_type));
1909       return type_instance;
1910     }
1911
1912   return type_instance;
1913 }
1914
1915 GTypeClass*
1916 g_type_check_class_cast (GTypeClass *type_class,
1917                          GType       is_a_type)
1918 {
1919   if (!type_class)
1920     {
1921       g_warning ("invalid class cast from (NULL) pointer to `%s'",
1922                  type_descriptive_name (is_a_type));
1923       return type_class;
1924     }
1925   if (!G_TYPE_IS_CLASSED (type_class->g_type))
1926     {
1927       g_warning ("invalid unclassed type `%s' in class cast to `%s'",
1928                  type_descriptive_name (type_class->g_type),
1929                  type_descriptive_name (is_a_type));
1930       return type_class;
1931     }
1932   if (!g_type_is_a (type_class->g_type, is_a_type))
1933     {
1934       g_warning ("invalid class cast from `%s' to `%s'",
1935                  type_descriptive_name (type_class->g_type),
1936                  type_descriptive_name (is_a_type));
1937       return type_class;
1938     }
1939
1940   return type_class;
1941 }
1942
1943
1944 /* --- foreign prototypes --- */
1945 extern void     g_value_types_init      (void); /* sync with gvaluetypes.c */
1946 extern void     g_enum_types_init       (void); /* sync with genums.c */
1947 extern void     g_param_type_init       (void); /* sync with gparam.c */
1948 extern void     g_object_type_init      (void); /* sync with gobject.c */
1949 extern void     g_param_spec_types_init (void); /* sync with gparamspecs.c */
1950
1951
1952 /* --- initialization --- */
1953 void
1954 g_type_init (void)
1955 {
1956   static TypeNode *type0_node = NULL;
1957   GTypeInfo info;
1958   TypeNode *node;
1959   GType type;
1960
1961   if (G_TYPE_FUNDAMENTAL_LAST)
1962     return;
1963
1964   /* type qname hash table */
1965   g_type_nodes_ht = g_hash_table_new (g_direct_hash, g_direct_equal);
1966
1967   /* invalid type G_TYPE_INVALID (0)
1968    */
1969   _g_type_fundamental_last = 1;
1970   g_type_nodes = g_renew (TypeNode**, g_type_nodes, G_TYPE_FUNDAMENTAL_LAST);
1971   g_type_nodes[0] = &type0_node;
1972   g_branch_seqnos = g_renew (GType, g_branch_seqnos, G_TYPE_FUNDAMENTAL_LAST);
1973   g_branch_seqnos[0] = 1;
1974
1975   /* void type G_TYPE_NONE
1976    */
1977   node = type_node_fundamental_new (G_TYPE_NONE, "void", 0);
1978   type = NODE_TYPE (node);
1979   g_assert (type == G_TYPE_NONE);
1980
1981   /* interface fundamental type G_TYPE_INTERFACE (!classed)
1982    */
1983   memset (&info, 0, sizeof (info));
1984   node = type_node_fundamental_new (G_TYPE_INTERFACE, "GInterface", G_TYPE_FLAG_DERIVABLE);
1985   type = NODE_TYPE (node);
1986   type_data_make (node, &info, NULL); // FIXME
1987   g_assert (type == G_TYPE_INTERFACE);
1988
1989   /* G_TYPE_* value types
1990    */
1991   g_value_types_init ();
1992   
1993   /* G_TYPE_ENUM & G_TYPE_FLAGS
1994    */
1995   g_enum_types_init ();
1996   
1997   /* G_TYPE_PARAM
1998    */
1999   g_param_type_init ();
2000
2001   /* G_TYPE_OBJECT
2002    */
2003   g_object_type_init ();
2004
2005   /* G_TYPE_PARAM_* pspec types
2006    */
2007   g_param_spec_types_init ();
2008 }