Make work again.
[platform/upstream/glib.git] / gobject / gtypemodule.c
1 /* GObject - GLib Type, Object, Parameter and Signal Library
2  * Copyright (C) 2000 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 Public
15  * 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
20 #include <stdlib.h>
21
22 #include "gtypeplugin.h"
23 #include "gtypemodule.h"
24 #include "gobjectalias.h"
25
26 typedef struct _ModuleTypeInfo ModuleTypeInfo;
27 typedef struct _ModuleInterfaceInfo ModuleInterfaceInfo;
28
29 struct _ModuleTypeInfo 
30 {
31   gboolean  loaded;
32   GType     type;
33   GType     parent_type;
34   GTypeInfo info;
35 };
36
37 struct _ModuleInterfaceInfo 
38 {
39   gboolean       loaded;
40   GType          instance_type;
41   GType          interface_type;
42   GInterfaceInfo info;
43 };
44
45 static void g_type_module_use_plugin              (GTypePlugin     *plugin);
46 static void g_type_module_complete_type_info      (GTypePlugin     *plugin,
47                                                    GType            g_type,
48                                                    GTypeInfo       *info,
49                                                    GTypeValueTable *value_table);
50 static void g_type_module_complete_interface_info (GTypePlugin     *plugin,
51                                                    GType            instance_type,
52                                                    GType            interface_type,
53                                                    GInterfaceInfo  *info);
54  
55 static gpointer parent_class = NULL;
56
57 static void
58 g_type_module_dispose (GObject *object)
59 {
60   GTypeModule *module = G_TYPE_MODULE (object);
61   
62   if (module->type_infos || module->interface_infos)
63     {
64       g_warning (G_STRLOC ": unsolicitated invocation of g_object_dispose() on GTypeModule");
65              
66       g_object_ref (object);
67     }
68
69   G_OBJECT_CLASS (parent_class)->dispose (object);
70 }
71
72 static void
73 g_type_module_finalize (GObject *object)
74 {
75   GTypeModule *module = G_TYPE_MODULE (object);
76
77   g_free (module->name);
78
79   G_OBJECT_CLASS (parent_class)->finalize (object);
80 }
81
82 static void
83 g_type_module_class_init (GTypeModuleClass *class)
84 {
85   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
86
87   parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (class));
88   
89   gobject_class->dispose = g_type_module_dispose;
90   gobject_class->finalize = g_type_module_finalize;
91 }
92
93 static void
94 g_type_module_iface_init (GTypePluginClass *iface)
95 {
96   iface->use_plugin = g_type_module_use_plugin;
97   iface->unuse_plugin = (void (*) (GTypePlugin *))g_type_module_unuse;
98   iface->complete_type_info = g_type_module_complete_type_info;
99   iface->complete_interface_info = g_type_module_complete_interface_info;
100 }
101
102 GType
103 g_type_module_get_type (void)
104 {
105   static GType type_module_type = 0;
106
107   if (!type_module_type)
108     {
109       static const GTypeInfo type_module_info = {
110         sizeof (GTypeModuleClass),
111         NULL,           /* base_init */
112         NULL,           /* base_finalize */
113         (GClassInitFunc) g_type_module_class_init,
114         NULL,           /* class_finalize */
115         NULL,           /* class_data */
116         sizeof (GTypeModule),
117         0,              /* n_preallocs */
118         NULL,           /* instance_init */
119       };
120       static const GInterfaceInfo iface_info = {
121         (GInterfaceInitFunc) g_type_module_iface_init,
122         NULL,               /* interface_finalize */
123         NULL,               /* interface_data */
124       };
125
126       type_module_type = g_type_register_static (G_TYPE_OBJECT, "GTypeModule", &type_module_info, G_TYPE_FLAG_ABSTRACT);
127
128       g_type_add_interface_static (type_module_type, G_TYPE_TYPE_PLUGIN, &iface_info);
129     }
130   
131   return type_module_type;
132 }
133
134 void
135 g_type_module_set_name (GTypeModule  *module,
136                         const gchar  *name)
137 {
138   g_return_if_fail (G_IS_TYPE_MODULE (module));
139
140   g_free (module->name);
141   module->name = g_strdup (name);
142 }
143
144 static ModuleTypeInfo *
145 g_type_module_find_type_info (GTypeModule *module,
146                               GType        type)
147 {
148   GSList *tmp_list = module->type_infos;
149   while (tmp_list)
150     {
151       ModuleTypeInfo *type_info = tmp_list->data;
152       if (type_info->type == type)
153         return type_info;
154       
155       tmp_list = tmp_list->next;
156     }
157
158   return NULL;
159 }
160
161 static ModuleInterfaceInfo *
162 g_type_module_find_interface_info (GTypeModule *module,
163                                    GType        instance_type,
164                                    GType        interface_type)
165 {
166   GSList *tmp_list = module->interface_infos;
167   while (tmp_list)
168     {
169       ModuleInterfaceInfo *interface_info = tmp_list->data;
170       if (interface_info->instance_type == instance_type &&
171           interface_info->interface_type == interface_type)
172         return interface_info;
173       
174       tmp_list = tmp_list->next;
175     }
176
177   return NULL;
178 }
179
180 gboolean
181 g_type_module_use (GTypeModule *module)
182 {
183   g_return_val_if_fail (G_IS_TYPE_MODULE (module), FALSE);
184
185   module->use_count++;
186   if (module->use_count == 1)
187     {
188       GSList *tmp_list;
189       
190       if (!G_TYPE_MODULE_GET_CLASS (module)->load (module))
191         {
192           module->use_count--;
193           return FALSE;
194         }
195
196       tmp_list = module->type_infos;
197       while (tmp_list)
198         {
199           ModuleTypeInfo *type_info = tmp_list->data;
200           if (!type_info->loaded)
201             {
202               g_warning ("plugin '%s' failed to register type '%s'\n",
203                          module->name ? module->name : "(unknown)",
204                          g_type_name (type_info->type));
205               return FALSE;
206             }
207           
208           tmp_list = tmp_list->next;
209         }
210     }
211  
212   return TRUE;
213 }
214
215 void
216 g_type_module_unuse (GTypeModule *module)
217 {
218   g_return_if_fail (G_IS_TYPE_MODULE (module));
219   g_return_if_fail (module->use_count > 0);
220
221   module->use_count--;
222
223   if (module->use_count == 0)
224     {
225       GSList *tmp_list;
226
227       G_TYPE_MODULE_GET_CLASS (module)->unload (module);
228
229       tmp_list = module->type_infos;
230       while (tmp_list)
231         {
232           ModuleTypeInfo *type_info = tmp_list->data;
233           type_info->loaded = FALSE;
234
235           tmp_list = tmp_list->next;
236         }
237     }
238 }
239         
240 static void
241 g_type_module_use_plugin (GTypePlugin *plugin)
242 {
243   GTypeModule *module = G_TYPE_MODULE (plugin);
244
245   if (!g_type_module_use (module))
246     {
247       g_warning ("Fatal error - Could not reload previously loaded plugin '%s'\n",
248                  module->name ? module->name : "(unknown)");
249       exit (1);
250     }
251 }
252
253 static void
254 g_type_module_complete_type_info (GTypePlugin     *plugin,
255                                   GType            g_type,
256                                   GTypeInfo       *info,
257                                   GTypeValueTable *value_table)
258 {
259   GTypeModule *module = G_TYPE_MODULE (plugin);
260   ModuleTypeInfo *module_type_info = g_type_module_find_type_info (module, g_type);
261
262   *info = module_type_info->info;
263   
264   if (module_type_info->info.value_table)
265     *value_table = *module_type_info->info.value_table;
266 }
267
268 static void 
269 g_type_module_complete_interface_info (GTypePlugin    *plugin,
270                                        GType           instance_type,
271                                        GType           interface_type,
272                                        GInterfaceInfo *info)
273 {
274   GTypeModule *module = G_TYPE_MODULE (plugin);
275   ModuleInterfaceInfo *module_interface_info = g_type_module_find_interface_info (module, instance_type, interface_type);
276
277   *info = module_interface_info->info;
278 }
279
280 GType
281 g_type_module_register_type (GTypeModule     *module,
282                              GType            parent_type,
283                              const gchar     *type_name,
284                              const GTypeInfo *type_info,
285                              GTypeFlags       flags)
286 {
287   ModuleTypeInfo *module_type_info = NULL;
288   GType type;
289   
290   g_return_val_if_fail (module != NULL, 0);
291   g_return_val_if_fail (type_name != NULL, 0);
292   g_return_val_if_fail (type_info != NULL, 0);
293
294   type = g_type_from_name (type_name);
295   if (type)
296     {
297       GTypePlugin *old_plugin = g_type_get_plugin (type);
298
299       if (old_plugin != G_TYPE_PLUGIN (module))
300         {
301           g_warning ("Two different plugins tried to register '%s'.", type_name);
302           return 0;
303         }
304     }
305
306   if (type)
307     {
308       module_type_info = g_type_module_find_type_info (module, type);
309
310       if (module_type_info->parent_type != parent_type)
311         {
312           const gchar *parent_type_name = g_type_name (parent_type);
313           
314           g_warning ("Type '%s' recreated with different parent type.\n"
315                      "(was '%s', now '%s')", type_name,
316                      g_type_name (module_type_info->parent_type),
317                      parent_type_name ? parent_type_name : "(unknown)");
318           return 0;
319         }
320
321       if (module_type_info->info.value_table)
322         g_free ((GTypeValueTable *) module_type_info->info.value_table);
323     }
324   else
325     {
326       module_type_info = g_new (ModuleTypeInfo, 1);
327       
328       module_type_info->parent_type = parent_type;
329       module_type_info->type = g_type_register_dynamic (parent_type, type_name, G_TYPE_PLUGIN (module), flags);
330       
331       module->type_infos = g_slist_prepend (module->type_infos, module_type_info);
332     }
333
334   module_type_info->loaded = TRUE;
335   module_type_info->info = *type_info;
336   if (type_info->value_table)
337     module_type_info->info.value_table = g_memdup (type_info->value_table,
338                                                    sizeof (type_info->value_table));
339
340   return module_type_info->type;
341 }
342
343 void
344 g_type_module_add_interface (GTypeModule          *module,
345                              GType                 instance_type,
346                              GType                 interface_type,
347                              const GInterfaceInfo *interface_info)
348 {
349   ModuleInterfaceInfo *module_interface_info = NULL;
350   
351   g_return_if_fail (module != NULL);
352   g_return_if_fail (interface_info != NULL);
353
354   if (g_type_is_a (instance_type, interface_type))
355     {
356       GTypePlugin *old_plugin = g_type_interface_get_plugin (instance_type,
357                                                              interface_type);
358
359       if (!old_plugin)
360         {
361           g_warning ("Interface '%s' for '%s' was previously registered statically or for a parent type.",
362                      g_type_name (interface_type), g_type_name (instance_type));
363           return;
364         }
365       else if (old_plugin != G_TYPE_PLUGIN (module))
366         {
367           g_warning ("Two different plugins tried to register interface '%s' for '%s'.",
368                      g_type_name (interface_type), g_type_name (instance_type));
369           return;
370         }
371       
372       module_interface_info = g_type_module_find_interface_info (module, instance_type, interface_type);
373
374       g_assert (module_interface_info);
375     }
376   else
377     {
378       module_interface_info = g_new (ModuleInterfaceInfo, 1);
379       
380       module_interface_info->instance_type = instance_type;
381       module_interface_info->interface_type = interface_type;
382       
383       g_type_add_interface_dynamic (instance_type, interface_type, G_TYPE_PLUGIN (module));
384       
385       module->interface_infos = g_slist_prepend (module->interface_infos, module_interface_info);
386     }
387   
388   module_interface_info->loaded = TRUE;
389   module_interface_info->info = *interface_info;
390 }
391
392 GType
393 g_type_module_register_enum (GTypeModule      *module,
394                              const gchar      *name,
395                              const GEnumValue *const_static_values)
396 {
397   GTypeInfo enum_type_info = { 0, };
398
399   g_return_val_if_fail (G_IS_TYPE_MODULE (module), 0);
400   g_return_val_if_fail (name != NULL, 0);
401   g_return_val_if_fail (const_static_values != NULL, 0);
402
403   g_enum_complete_type_info (G_TYPE_ENUM,
404                              &enum_type_info, const_static_values);
405
406   return g_type_module_register_type (G_TYPE_MODULE (module),
407                                       G_TYPE_ENUM, name, &enum_type_info, 0);
408 }
409
410 GType
411 g_type_module_register_flags (GTypeModule      *module,
412                              const gchar       *name,
413                              const GFlagsValue *const_static_values)
414 {
415   GTypeInfo flags_type_info = { 0, };
416
417   g_return_val_if_fail (G_IS_TYPE_MODULE (module), 0);
418   g_return_val_if_fail (name != NULL, 0);
419   g_return_val_if_fail (const_static_values != NULL, 0);
420
421   g_flags_complete_type_info (G_TYPE_FLAGS,
422                              &flags_type_info, const_static_values);
423
424   return g_type_module_register_type (G_TYPE_MODULE (module),
425                                       G_TYPE_FLAGS, name, &flags_type_info, 0);
426 }
427
428
429 #define __G_TYPE_MODULE_C__
430 #include "gobjectaliasdef.c"