add reserved fundamental ids for gtk types (for transition time). added
[platform/upstream/glib.git] / gobject / gparam.c
1 /* GObject - GLib Type, Object, Parameter and Signal Library
2  * Copyright (C) 1997, 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        "gparam.h"
20
21
22 #include        <string.h>
23
24
25
26 /* --- defines --- */
27 #define G_PARAM_SPEC_CLASS(class)    (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_PARAM, GParamSpecClass))
28
29
30 /* --- prototypes --- */
31 extern void     g_param_types_init               (void);
32 extern void     g_param_spec_types_init          (void);        /* sync with glib-gparamspecs.c */
33 static void     g_param_spec_class_base_init     (GParamSpecClass       *class);
34 static void     g_param_spec_class_base_finalize (GParamSpecClass       *class);
35 static void     g_param_spec_class_init          (GParamSpecClass       *class,
36                                                   gpointer               class_data);
37 static void     g_param_spec_init                (GParamSpec            *pspec);
38 static void     g_param_spec_finalize            (GParamSpec            *pspec);
39
40
41 /* --- functions --- */
42 void
43 g_param_types_init (void)       /* sync with glib-gtype.c */
44 {
45   static const GTypeFundamentalInfo finfo = {
46     (G_TYPE_FLAG_CLASSED |
47      G_TYPE_FLAG_INSTANTIATABLE |
48      G_TYPE_FLAG_DERIVABLE |
49      G_TYPE_FLAG_DEEP_DERIVABLE),
50     0           /* n_collect_bytes */,
51     NULL        /* GTypeParamCollector */,
52   };
53   static const GTypeInfo param_spec_info = {
54     sizeof (GParamSpecClass),
55
56     (GBaseInitFunc) g_param_spec_class_base_init,
57     (GBaseFinalizeFunc) g_param_spec_class_base_finalize,
58     (GClassInitFunc) g_param_spec_class_init,
59     (GClassFinalizeFunc) NULL,
60     NULL /* class_data */,
61
62     sizeof (GParamSpec),
63     0 /* n_preallocs */,
64     (GInstanceInitFunc) g_param_spec_init,
65   };
66   GType type;
67
68   type = g_type_register_fundamental (G_TYPE_PARAM, "GParam", &finfo, &param_spec_info);
69   g_assert (type == G_TYPE_PARAM);
70
71   /* derived param specs
72    */
73   g_param_spec_types_init ();
74 }
75
76 static void
77 g_param_spec_class_base_init (GParamSpecClass *class)
78 {
79 }
80
81 static void
82 g_param_spec_class_base_finalize (GParamSpecClass *class)
83 {
84 }
85
86 static void
87 g_param_spec_class_init (GParamSpecClass *class,
88                          gpointer         class_data)
89 {
90   class->finalize = g_param_spec_finalize;
91   class->param_init = NULL;
92   class->param_free_value = NULL;
93   class->param_validate = NULL;
94   class->param_values_cmp = NULL;
95   class->param_copy_value = NULL;
96   class->collect_type = 0;
97   class->param_collect_value = NULL;
98   class->lcopy_type = 0;
99   class->param_lcopy_value = NULL;
100 }
101
102 static void
103 g_param_spec_init (GParamSpec *pspec)
104 {
105   pspec->name = NULL;
106   pspec->nick = NULL;
107   pspec->blurb = NULL;
108   pspec->flags = 0;
109   pspec->owner_type = 0;
110   pspec->qdata = NULL;
111   pspec->ref_count = 1;
112 }
113
114 static void
115 g_param_spec_finalize (GParamSpec *pspec)
116 {
117   g_datalist_clear (&pspec->qdata);
118   
119   g_free (pspec->name);
120   g_free (pspec->nick);
121   g_free (pspec->blurb);
122
123   g_type_free_instance ((GTypeInstance*) pspec);
124 }
125
126 GParamSpec*
127 g_param_spec_ref (GParamSpec *pspec)
128 {
129   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
130   g_return_val_if_fail (pspec->ref_count > 0, NULL);
131
132   pspec->ref_count += 1;
133
134   return pspec;
135 }
136
137 void
138 g_param_spec_unref (GParamSpec *pspec)
139 {
140   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
141   g_return_if_fail (pspec->ref_count > 0);
142
143   pspec->ref_count -= 1;
144   if (pspec->ref_count == 0)
145     G_PARAM_SPEC_GET_CLASS (pspec)->finalize (pspec);
146 }
147
148 gpointer
149 g_param_spec_internal (GType        param_type,
150                        const gchar *name,
151                        const gchar *nick,
152                        const gchar *blurb,
153                        GParamFlags  flags)
154 {
155   GParamSpec *pspec;
156
157   g_return_val_if_fail (G_TYPE_IS_PARAM (param_type) && param_type != G_TYPE_PARAM, NULL);
158   g_return_val_if_fail (name != NULL, NULL);
159
160   pspec = (gpointer) g_type_create_instance (param_type);
161   pspec->name = g_strdup (name);
162   g_strcanon (pspec->name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-');
163   pspec->nick = g_strdup (nick ? nick : pspec->name);
164   pspec->blurb = g_strdup (blurb);
165   pspec->flags = (flags & G_PARAM_USER_MASK) | (flags & G_PARAM_MASK);
166
167   return pspec;
168 }
169
170 gpointer
171 g_param_spec_get_qdata (GParamSpec *pspec,
172                         GQuark      quark)
173 {
174   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
175   
176   return quark ? g_datalist_id_get_data (&pspec->qdata, quark) : NULL;
177 }
178
179 void
180 g_param_spec_set_qdata (GParamSpec *pspec,
181                         GQuark      quark,
182                         gpointer    data)
183 {
184   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
185   g_return_if_fail (quark > 0);
186
187   g_datalist_id_set_data (&pspec->qdata, quark, data);
188 }
189
190 void
191 g_param_spec_set_qdata_full (GParamSpec    *pspec,
192                              GQuark         quark,
193                              gpointer       data,
194                              GDestroyNotify destroy)
195 {
196   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
197   g_return_if_fail (quark > 0);
198
199   g_datalist_id_set_data_full (&pspec->qdata, quark, data, data ? destroy : NULL);
200 }
201
202 gpointer
203 g_param_spec_steal_qdata (GParamSpec *pspec,
204                           GQuark      quark)
205 {
206   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
207   g_return_val_if_fail (quark > 0, NULL);
208   
209   return g_datalist_id_remove_no_notify (&pspec->qdata, quark);
210 }
211
212 static guint
213 param_spec_hash (gconstpointer key_spec)
214 {
215   const GParamSpec *key = key_spec;
216   const gchar *p;
217   guint h = key->owner_type;
218
219   for (p = key->name; *p; p++)
220     h = (h << 5) - h + *p;
221
222   return h;
223 }
224
225 static gint
226 param_spec_equals (gconstpointer key_spec_1,
227                    gconstpointer key_spec_2)
228 {
229   const GParamSpec *key1 = key_spec_1;
230   const GParamSpec *key2 = key_spec_2;
231
232   return (key1->owner_type == key2->owner_type &&
233           strcmp (key1->name, key2->name) == 0);
234 }
235
236 GHashTable*
237 g_param_spec_hash_table_new (void)
238 {
239   return g_hash_table_new (param_spec_hash, param_spec_equals);
240 }
241
242 void
243 g_param_spec_hash_table_insert (GHashTable *hash_table,
244                                 GParamSpec *pspec,
245                                 GType       owner_type)
246 {
247   g_return_if_fail (hash_table != NULL);
248   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
249   g_return_if_fail (pspec->name != NULL);
250   if (pspec->owner_type != owner_type)
251     g_return_if_fail (pspec->owner_type == 0);
252
253   if (strchr (pspec->name, ':'))
254     g_warning (G_STRLOC ": parameter name `%s' contains field-delimeter",
255                pspec->name);
256   else
257     {
258       pspec->owner_type = owner_type;
259       g_hash_table_insert (hash_table, pspec, pspec);
260     }
261 }
262
263 void
264 g_param_spec_hash_table_remove (GHashTable *hash_table,
265                                 GParamSpec *pspec)
266 {
267   g_return_if_fail (hash_table != NULL);
268   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
269
270   g_assert (g_param_spec_hash_table_lookup (hash_table, pspec->name, pspec->owner_type, FALSE, NULL) != NULL); // FIXME: paranoid
271
272   g_hash_table_remove (hash_table, pspec);
273   g_assert (g_param_spec_hash_table_lookup (hash_table, pspec->name, pspec->owner_type, FALSE, NULL) == NULL); // FIXME: paranoid
274   pspec->owner_type = 0;
275 }
276
277 GParamSpec*
278 g_param_spec_hash_table_lookup (GHashTable   *hash_table,
279                                 const gchar  *param_name,
280                                 GType         owner_type,
281                                 gboolean      try_ancestors,
282                                 const gchar **trailer)
283 {
284   GParamSpec *pspec;
285   GParamSpec key;
286   gchar *delim;
287   
288   g_return_val_if_fail (hash_table != NULL, NULL);
289   g_return_val_if_fail (param_name != NULL, NULL);
290   
291   key.owner_type = owner_type;
292   delim = strchr (param_name, ':');
293   if (delim)
294     key.name = g_strndup (param_name, delim - param_name);
295   else
296     key.name = g_strdup (param_name);
297   g_strcanon (key.name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-');
298
299   if (trailer)
300     *trailer = delim;
301   
302   pspec = g_hash_table_lookup (hash_table, &key);
303   if (!pspec && try_ancestors)
304     {
305       key.owner_type = g_type_parent (key.owner_type);
306       while (key.owner_type)
307         {
308           pspec = g_hash_table_lookup (hash_table, &key);
309           if (pspec)
310             break;
311           key.owner_type = g_type_parent (key.owner_type);
312         }
313     }
314   
315   g_free (key.name);
316   
317   return pspec;
318 }