add an instance member value_type so the default value of the pspec class
[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        "gvaluecollector.h"
23 #include        <string.h>
24
25
26
27 /* --- defines --- */
28 #define G_PARAM_SPEC_CLASS(class)    (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_PARAM, GParamSpecClass))
29 #define PSPEC_APPLIES_TO_VALUE(pspec, value)  (G_TYPE_CHECK_VALUE_TYPE ((value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
30
31
32 /* --- prototypes --- */
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                                                   GParamSpecClass       *class);
39 static void     g_param_spec_finalize            (GParamSpec            *pspec);
40 static void     value_param_init                (GValue         *value);
41 static void     value_param_free_value          (GValue         *value);
42 static void     value_param_copy_value          (const GValue   *src_value,
43                                                  GValue         *dest_value);
44 static gpointer value_param_peek_pointer        (const GValue   *value);
45 static gchar*   value_param_collect_value       (GValue         *value,
46                                                  guint           nth_value,
47                                                  GType          *collect_type,
48                                                  GTypeCValue    *collect_value);
49 static gchar*   value_param_lcopy_value         (const GValue   *value,
50                                                  guint           nth_value,
51                                                  GType          *collect_type,
52                                                  GTypeCValue    *collect_value);
53
54
55 /* --- variables --- */
56 static GQuark quark_floating = 0;
57
58
59 /* --- functions --- */
60 void
61 g_param_type_init (void)        /* sync with gtype.c */
62 {
63   static const GTypeFundamentalInfo finfo = {
64     (G_TYPE_FLAG_CLASSED |
65      G_TYPE_FLAG_INSTANTIATABLE |
66      G_TYPE_FLAG_DERIVABLE |
67      G_TYPE_FLAG_DEEP_DERIVABLE),
68   };
69   static const GTypeValueTable param_value_table = {
70     value_param_init,           /* value_init */
71     value_param_free_value,     /* value_free */
72     value_param_copy_value,     /* value_copy */
73     value_param_peek_pointer,   /* value_peek_pointer */
74     G_VALUE_COLLECT_POINTER,    /* collect_type */
75     value_param_collect_value,  /* collect_value */
76     G_VALUE_COLLECT_POINTER,    /* lcopy_type */
77     value_param_lcopy_value,    /* lcopy_value */
78   };
79   static const GTypeInfo param_spec_info = {
80     sizeof (GParamSpecClass),
81
82     (GBaseInitFunc) g_param_spec_class_base_init,
83     (GBaseFinalizeFunc) g_param_spec_class_base_finalize,
84     (GClassInitFunc) g_param_spec_class_init,
85     (GClassFinalizeFunc) NULL,
86     NULL,       /* class_data */
87
88     sizeof (GParamSpec),
89     0,          /* n_preallocs */
90     (GInstanceInitFunc) g_param_spec_init,
91
92     &param_value_table,
93   };
94   GType type;
95
96   type = g_type_register_fundamental (G_TYPE_PARAM, "GParam", &param_spec_info, &finfo, G_TYPE_FLAG_ABSTRACT);
97   g_assert (type == G_TYPE_PARAM);
98 }
99
100 static void
101 g_param_spec_class_base_init (GParamSpecClass *class)
102 {
103 }
104
105 static void
106 g_param_spec_class_base_finalize (GParamSpecClass *class)
107 {
108 }
109
110 static void
111 g_param_spec_class_init (GParamSpecClass *class,
112                          gpointer         class_data)
113 {
114   quark_floating = g_quark_from_static_string ("GParamSpec-floating");
115
116   class->value_type = G_TYPE_NONE;
117   class->finalize = g_param_spec_finalize;
118   class->value_set_default = NULL;
119   class->value_validate = NULL;
120   class->values_cmp = NULL;
121 }
122
123 static void
124 g_param_spec_init (GParamSpec      *pspec,
125                    GParamSpecClass *class)
126 {
127   pspec->name = NULL;
128   pspec->nick = NULL;
129   pspec->blurb = NULL;
130   pspec->flags = 0;
131   pspec->value_type = class->value_type;
132   pspec->owner_type = 0;
133   pspec->qdata = NULL;
134   pspec->ref_count = 1;
135   g_datalist_id_set_data (&pspec->qdata, quark_floating, GUINT_TO_POINTER (TRUE));
136 }
137
138 static void
139 g_param_spec_finalize (GParamSpec *pspec)
140 {
141   g_datalist_clear (&pspec->qdata);
142   
143   g_free (pspec->name);
144   g_free (pspec->nick);
145   g_free (pspec->blurb);
146
147   g_type_free_instance ((GTypeInstance*) pspec);
148 }
149
150 GParamSpec*
151 g_param_spec_ref (GParamSpec *pspec)
152 {
153   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
154   g_return_val_if_fail (pspec->ref_count > 0, NULL);
155
156   pspec->ref_count += 1;
157
158   return pspec;
159 }
160
161 void
162 g_param_spec_unref (GParamSpec *pspec)
163 {
164   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
165   g_return_if_fail (pspec->ref_count > 0);
166
167   /* sync with _sink */
168   pspec->ref_count -= 1;
169   if (pspec->ref_count == 0)
170     G_PARAM_SPEC_GET_CLASS (pspec)->finalize (pspec);
171 }
172
173 void
174 g_param_spec_sink (GParamSpec *pspec)
175 {
176   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
177   g_return_if_fail (pspec->ref_count > 0);
178
179   if (g_datalist_id_remove_no_notify (&pspec->qdata, quark_floating))
180     {
181       /* sync with _unref */
182       if (pspec->ref_count > 1)
183         pspec->ref_count -= 1;
184       else
185         g_param_spec_unref (pspec);
186     }
187 }
188
189 gpointer
190 g_param_spec_internal (GType        param_type,
191                        const gchar *name,
192                        const gchar *nick,
193                        const gchar *blurb,
194                        GParamFlags  flags)
195 {
196   GParamSpec *pspec;
197
198   g_return_val_if_fail (G_TYPE_IS_PARAM (param_type) && param_type != G_TYPE_PARAM, NULL);
199   g_return_val_if_fail (name != NULL, NULL);
200
201   pspec = (gpointer) g_type_create_instance (param_type);
202   pspec->name = g_strdup (name);
203   g_strcanon (pspec->name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-');
204   pspec->nick = g_strdup (nick ? nick : pspec->name);
205   pspec->blurb = g_strdup (blurb);
206   pspec->flags = (flags & G_PARAM_USER_MASK) | (flags & G_PARAM_MASK);
207
208   return pspec;
209 }
210
211 gpointer
212 g_param_spec_get_qdata (GParamSpec *pspec,
213                         GQuark      quark)
214 {
215   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
216   
217   return quark ? g_datalist_id_get_data (&pspec->qdata, quark) : NULL;
218 }
219
220 void
221 g_param_spec_set_qdata (GParamSpec *pspec,
222                         GQuark      quark,
223                         gpointer    data)
224 {
225   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
226   g_return_if_fail (quark > 0);
227
228   g_datalist_id_set_data (&pspec->qdata, quark, data);
229 }
230
231 void
232 g_param_spec_set_qdata_full (GParamSpec    *pspec,
233                              GQuark         quark,
234                              gpointer       data,
235                              GDestroyNotify destroy)
236 {
237   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
238   g_return_if_fail (quark > 0);
239
240   g_datalist_id_set_data_full (&pspec->qdata, quark, data, data ? destroy : (GDestroyNotify) NULL);
241 }
242
243 gpointer
244 g_param_spec_steal_qdata (GParamSpec *pspec,
245                           GQuark      quark)
246 {
247   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
248   g_return_val_if_fail (quark > 0, NULL);
249   
250   return g_datalist_id_remove_no_notify (&pspec->qdata, quark);
251 }
252
253 void
254 g_param_value_set_default (GParamSpec *pspec,
255                            GValue     *value)
256 {
257   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
258   g_return_if_fail (G_IS_VALUE (value));
259   g_return_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value));
260
261   g_value_reset (value);
262   G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, value);
263 }
264
265 gboolean
266 g_param_value_defaults (GParamSpec *pspec,
267                         GValue     *value)
268 {
269   GValue dflt_value = { 0, };
270   gboolean defaults;
271
272   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
273   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
274   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE);
275
276   g_value_init (&dflt_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
277   G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, &dflt_value);
278   defaults = G_PARAM_SPEC_GET_CLASS (pspec)->values_cmp (pspec, value, &dflt_value) == 0;
279   g_value_unset (&dflt_value);
280
281   return defaults;
282 }
283
284 gboolean
285 g_param_value_validate (GParamSpec *pspec,
286                         GValue     *value)
287 {
288   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
289   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
290   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE);
291
292   if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate)
293     {
294       GValue oval = *value;
295
296       if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate (pspec, value) ||
297           memcmp (&oval.data, &value->data, sizeof (oval.data)))
298         return TRUE;
299     }
300
301   return FALSE;
302 }
303
304 gint
305 g_param_values_cmp (GParamSpec   *pspec,
306                     const GValue *value1,
307                     const GValue *value2)
308 {
309   gint cmp;
310
311   /* param_values_cmp() effectively does: value1 - value2
312    * so the return values are:
313    * -1)  value1 < value2
314    *  0)  value1 == value2
315    *  1)  value1 > value2
316    */
317   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), 0);
318   g_return_val_if_fail (G_IS_VALUE (value1), 0);
319   g_return_val_if_fail (G_IS_VALUE (value2), 0);
320   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value1), 0);
321   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value2), 0);
322
323   cmp = G_PARAM_SPEC_GET_CLASS (pspec)->values_cmp (pspec, value1, value2);
324
325   return CLAMP (cmp, -1, 1);
326 }
327
328 static void
329 value_param_init (GValue *value)
330 {
331   value->data[0].v_pointer = NULL;
332 }
333
334 static void
335 value_param_free_value (GValue *value)
336 {
337   if (value->data[0].v_pointer)
338     g_param_spec_unref (value->data[0].v_pointer);
339 }
340
341 static void
342 value_param_copy_value (const GValue *src_value,
343                         GValue       *dest_value)
344 {
345   dest_value->data[0].v_pointer = (src_value->data[0].v_pointer
346                                    ? g_param_spec_ref (src_value->data[0].v_pointer)
347                                    : NULL);
348 }
349
350 static gpointer
351 value_param_peek_pointer (const GValue *value)
352 {
353   return value->data[0].v_pointer;
354 }
355
356 static gchar*
357 value_param_collect_value (GValue      *value,
358                            guint        nth_value,
359                            GType       *collect_type,
360                            GTypeCValue *collect_value)
361 {
362   if (collect_value->v_pointer)
363     {
364       GParamSpec *param = collect_value->v_pointer;
365
366       if (param->g_type_instance.g_class == NULL)
367         return g_strconcat ("invalid unclassed param spec pointer for value type `",
368                             G_VALUE_TYPE_NAME (value),
369                             "'",
370                             NULL);
371       else if (!g_type_is_a (G_PARAM_SPEC_TYPE (param), G_VALUE_TYPE (value)))
372         return g_strconcat ("invalid param spec type `",
373                             G_PARAM_SPEC_TYPE_NAME (param),
374                             "' for value type `",
375                             G_VALUE_TYPE_NAME (value),
376                             "'",
377                             NULL);
378       value->data[0].v_pointer = g_param_spec_ref (param);
379     }
380   else
381     value->data[0].v_pointer = NULL;
382
383   *collect_type = 0;
384   return NULL;
385 }
386
387 static gchar*
388 value_param_lcopy_value (const GValue *value,
389                          guint         nth_value,
390                          GType        *collect_type,
391                          GTypeCValue  *collect_value)
392 {
393   GParamSpec **param_p = collect_value->v_pointer;
394
395   if (!param_p)
396     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
397
398   *param_p = value->data[0].v_pointer ? g_param_spec_ref (value->data[0].v_pointer) : NULL;
399
400   *collect_type = 0;
401   return NULL;
402 }
403
404
405 /* --- param spec pool --- */
406 struct _GParamSpecPool
407 {
408   gboolean    type_prefixing;
409   GHashTable *hash_table;
410 };
411
412 static guint
413 param_spec_pool_hash (gconstpointer key_spec)
414 {
415   const GParamSpec *key = key_spec;
416   const gchar *p;
417   guint h = key->owner_type;
418
419   for (p = key->name; *p; p++)
420     h = (h << 5) - h + *p;
421
422   return h;
423 }
424
425 static gboolean
426 param_spec_pool_equals (gconstpointer key_spec_1,
427                         gconstpointer key_spec_2)
428 {
429   const GParamSpec *key1 = key_spec_1;
430   const GParamSpec *key2 = key_spec_2;
431
432   return (key1->owner_type == key2->owner_type &&
433           strcmp (key1->name, key2->name) == 0);
434 }
435
436 GParamSpecPool*
437 g_param_spec_pool_new (gboolean type_prefixing)
438 {
439   GParamSpecPool *pool = g_new (GParamSpecPool, 1);
440
441   pool->type_prefixing = type_prefixing != FALSE;
442   pool->hash_table = g_hash_table_new (param_spec_pool_hash, param_spec_pool_equals);
443
444   return pool;
445 }
446
447 void
448 g_param_spec_pool_insert (GParamSpecPool *pool,
449                           GParamSpec     *pspec,
450                           GType           owner_type)
451 {
452   gchar *p;
453
454   g_return_if_fail (pool != NULL);
455   g_return_if_fail (pspec);
456   g_return_if_fail (owner_type > 0);
457   g_return_if_fail (pspec->owner_type == 0);
458
459   for (p = pspec->name; *p; p++)
460     {
461       if (!strchr (G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-_", *p))
462         {
463           g_warning (G_STRLOC ": pspec name \"%s\" contains invalid characters", pspec->name);
464           return;
465         }
466     }
467
468   pspec->owner_type = owner_type;
469   g_param_spec_ref (pspec);
470   g_hash_table_insert (pool->hash_table, pspec, pspec);
471 }
472
473 void
474 g_param_spec_pool_remove (GParamSpecPool *pool,
475                           GParamSpec     *pspec)
476 {
477   g_return_if_fail (pool != NULL);
478   g_return_if_fail (pspec);
479
480   if (g_hash_table_remove (pool->hash_table, pspec))
481     g_param_spec_unref (pspec);
482   else
483     g_warning (G_STRLOC ": attempt to remove unknown pspec `%s' from pool", pspec->name);
484 }
485
486 static inline GParamSpec*
487 param_spec_ht_lookup (GHashTable  *hash_table,
488                       const gchar *param_name,
489                       GType        owner_type,
490                       gboolean     walk_ancestors)
491 {
492   GParamSpec key, *pspec;
493
494   key.owner_type = owner_type;
495   key.name = (gchar*) param_name;
496   if (walk_ancestors)
497     do
498       {
499         pspec = g_hash_table_lookup (hash_table, &key);
500         if (pspec)
501           return pspec;
502         key.owner_type = g_type_parent (key.owner_type);
503       }
504     while (key.owner_type);
505   else
506     pspec = g_hash_table_lookup (hash_table, &key);
507
508   if (!pspec)
509     {
510       /* sigh, try canonicalization */
511       key.name = g_strdup (param_name);
512       key.owner_type = owner_type;
513       
514       g_strcanon (key.name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-');
515       if (walk_ancestors)
516         do
517           {
518             pspec = g_hash_table_lookup (hash_table, &key);
519             if (pspec)
520               {
521                 g_free (key.name);
522                 return pspec;
523               }
524             key.owner_type = g_type_parent (key.owner_type);
525           }
526         while (key.owner_type);
527       else
528         pspec = g_hash_table_lookup (hash_table, &key);
529       g_free (key.name);
530     }
531
532   return pspec;
533 }
534
535 GParamSpec*
536 g_param_spec_pool_lookup (GParamSpecPool *pool,
537                           const gchar    *param_name,
538                           GType           owner_type,
539                           gboolean        walk_ancestors,
540                           const gchar   **trailer_p)
541 {
542   GParamSpec *pspec;
543   gchar *delim;
544
545   g_return_val_if_fail (pool != NULL, NULL);
546   g_return_val_if_fail (param_name, NULL);
547
548   delim = strchr (param_name, ':');
549
550   /* try quick and away, i.e. no prefix, no trailer */
551   if (!delim)
552     {
553       if (trailer_p)
554         *trailer_p = NULL;
555       return param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
556     }
557
558   /* strip type prefix */
559   if (pool->type_prefixing && delim[1] == ':')
560     {
561       guint l = delim - param_name;
562       gchar stack_buffer[32], *buffer = l < 32 ? stack_buffer : g_new (gchar, l + 1);
563       GType type;
564       
565       strncpy (buffer, param_name, delim - param_name);
566       buffer[l] = 0;
567       type = g_type_from_name (buffer);
568       if (l >= 32)
569         g_free (buffer);
570       if (type)         /* type==0 isn't a valid type pefix */
571         {
572           /* sanity check, these cases don't make a whole lot of sense */
573           if ((!walk_ancestors && type != owner_type) || !g_type_is_a (owner_type, type))
574             {
575               if (trailer_p)
576                 *trailer_p = NULL;
577               return NULL;
578             }
579           owner_type = type;
580           param_name += l + 2;
581           delim = strchr (param_name, ':');
582           if (!delim)           /* good, can still forget about trailer */
583             {
584               if (trailer_p)
585                 *trailer_p = NULL;
586               return param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
587             }
588         }
589     }
590
591   /* ok, no prefix, handle trailer */
592   if (delim[1] == ':')
593     {
594       guint l = delim - param_name;
595       gchar stack_buffer[32], *buffer = l < 32 ? stack_buffer : g_new (gchar, l + 1);
596       
597       strncpy (buffer, param_name, delim - param_name);
598       buffer[l] = 0;
599       pspec = param_spec_ht_lookup (pool->hash_table, buffer, owner_type, walk_ancestors);
600       if (l >= 32)
601         g_free (buffer);
602       if (trailer_p)
603         *trailer_p = pspec ? delim + 2 : NULL;
604       return pspec;
605     }
606
607   /* malformed param_name */
608   if (trailer_p)
609     *trailer_p = NULL;
610   return NULL;
611 }
612
613
614 /* --- auxillary functions --- */
615 typedef struct
616 {
617   /* class portion */
618   GType           value_type;
619   void          (*finalize)             (GParamSpec   *pspec);
620   void          (*value_set_default)    (GParamSpec   *pspec,
621                                          GValue       *value);
622   gboolean      (*value_validate)       (GParamSpec   *pspec,
623                                          GValue       *value);
624   gint          (*values_cmp)           (GParamSpec   *pspec,
625                                          const GValue *value1,
626                                          const GValue *value2);
627 } ParamSpecClassInfo;
628
629 static void
630 param_spec_generic_class_init (gpointer g_class,
631                                gpointer class_data)
632 {
633   GParamSpecClass *class = g_class;
634   ParamSpecClassInfo *info = class_data;
635
636   class->value_type = info->value_type;
637   if (info->finalize)
638     class->finalize = info->finalize;                   /* optional */
639   class->value_set_default = info->value_set_default;
640   if (info->value_validate)
641     class->value_validate = info->value_validate;       /* optional */
642   class->values_cmp = info->values_cmp;
643   g_free (class_data);
644 }
645
646 static void
647 default_value_set_default (GParamSpec *pspec,
648                            GValue     *value)
649 {
650   /* value is already zero initialized */
651 }
652
653 static gint
654 default_values_cmp (GParamSpec   *pspec,
655                     const GValue *value1,
656                     const GValue *value2)
657 {
658   return memcmp (&value1->data, &value2->data, sizeof (value1->data));
659 }
660
661 GType
662 g_param_type_register_static (const gchar              *name,
663                               const GParamSpecTypeInfo *pspec_info)
664 {
665   GTypeInfo info = {
666     sizeof (GParamSpecClass),      /* class_size */
667     NULL,                          /* base_init */
668     NULL,                          /* base_destroy */
669     param_spec_generic_class_init, /* class_init */
670     NULL,                          /* class_destroy */
671     NULL,                          /* class_data */
672     0,                             /* instance_size */
673     16,                            /* n_preallocs */
674     NULL,                          /* instance_init */
675   };
676   ParamSpecClassInfo *cinfo;
677
678   g_return_val_if_fail (name != NULL, 0);
679   g_return_val_if_fail (pspec_info != NULL, 0);
680   g_return_val_if_fail (g_type_from_name (name) == 0, 0);
681   g_return_val_if_fail (pspec_info->instance_size >= sizeof (GParamSpec), 0);
682   g_return_val_if_fail (g_type_name (pspec_info->value_type) != NULL, 0);
683   /* default: g_return_val_if_fail (pspec_info->value_set_default != NULL, 0); */
684   /* optional: g_return_val_if_fail (pspec_info->value_validate != NULL, 0); */
685   /* default: g_return_val_if_fail (pspec_info->values_cmp != NULL, 0); */
686
687   info.instance_size = pspec_info->instance_size;
688   info.n_preallocs = pspec_info->n_preallocs;
689   info.instance_init = (GInstanceInitFunc) pspec_info->instance_init;
690   cinfo = g_new (ParamSpecClassInfo, 1);
691   cinfo->value_type = pspec_info->value_type;
692   cinfo->finalize = pspec_info->finalize;
693   cinfo->value_set_default = pspec_info->value_set_default ? pspec_info->value_set_default : default_value_set_default;
694   cinfo->value_validate = pspec_info->value_validate;
695   cinfo->values_cmp = pspec_info->values_cmp ? pspec_info->values_cmp : default_values_cmp;
696   info.class_data = cinfo;
697
698   return g_type_register_static (G_TYPE_PARAM, name, &info, 0);
699 }
700
701 void
702 g_value_set_param (GValue     *value,
703                    GParamSpec *param)
704 {
705   g_return_if_fail (G_IS_VALUE_PARAM (value));
706   if (param)
707     g_return_if_fail (G_IS_PARAM_SPEC (param));
708
709   if (value->data[0].v_pointer)
710     g_param_spec_unref (value->data[0].v_pointer);
711   value->data[0].v_pointer = param;
712   if (value->data[0].v_pointer)
713     g_param_spec_ref (value->data[0].v_pointer);
714 }
715
716 GParamSpec*
717 g_value_get_param (const GValue *value)
718 {
719   g_return_val_if_fail (G_IS_VALUE_PARAM (value), NULL);
720
721   return value->data[0].v_pointer;
722 }
723
724 GParamSpec*
725 g_value_dup_param (const GValue *value)
726 {
727   g_return_val_if_fail (G_IS_VALUE_PARAM (value), NULL);
728
729   return value->data[0].v_pointer ? g_param_spec_ref (value->data[0].v_pointer) : NULL;
730 }