GParamSpec: add g_param_spec_get_default_value()
[platform/upstream/glib.git] / gobject / gparam.c
1 /* GObject - GLib Type, Object, Parameter and Signal Library
2  * Copyright (C) 1997-1999, 2000-2001 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
20 /*
21  * MT safe
22  */
23
24 #include "config.h"
25
26 #include <string.h>
27
28 #include "gparam.h"
29 #include "gparamspecs.h"
30 #include "gvaluecollector.h"
31 #include "gtype-private.h"
32
33 /**
34  * SECTION:gparamspec
35  * @short_description: Metadata for parameter specifications
36  * @see_also: g_object_class_install_property(), g_object_set(),
37  *     g_object_get(), g_object_set_property(), g_object_get_property(),
38  *     g_value_register_transform_func()
39  * @title: GParamSpec
40  *
41  * #GParamSpec is an object structure that encapsulates the metadata
42  * required to specify parameters, such as e.g. #GObject properties.
43  *
44  * <para id="canonical-parameter-name">
45  * Parameter names need to start with a letter (a-z or A-Z). Subsequent
46  * characters can be letters, numbers or a '-'.
47  * All other characters are replaced by a '-' during construction.
48  * The result of this replacement is called the canonical name of the
49  * parameter.
50  * </para>
51  */
52
53
54 /* --- defines --- */
55 #define PARAM_FLOATING_FLAG                     0x2
56 #define G_PARAM_USER_MASK                       (~0 << G_PARAM_USER_SHIFT)
57 #define PSPEC_APPLIES_TO_VALUE(pspec, value)    (G_TYPE_CHECK_VALUE_TYPE ((value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
58
59 /* --- prototypes --- */
60 static void     g_param_spec_class_base_init     (GParamSpecClass       *class);
61 static void     g_param_spec_class_base_finalize (GParamSpecClass       *class);
62 static void     g_param_spec_class_init          (GParamSpecClass       *class,
63                                                   gpointer               class_data);
64 static void     g_param_spec_init                (GParamSpec            *pspec,
65                                                   GParamSpecClass       *class);
66 static void     g_param_spec_finalize            (GParamSpec            *pspec);
67 static void     value_param_init                (GValue         *value);
68 static void     value_param_free_value          (GValue         *value);
69 static void     value_param_copy_value          (const GValue   *src_value,
70                                                  GValue         *dest_value);
71 static void     value_param_transform_value     (const GValue   *src_value,
72                                                  GValue         *dest_value);
73 static gpointer value_param_peek_pointer        (const GValue   *value);
74 static gchar*   value_param_collect_value       (GValue         *value,
75                                                  guint           n_collect_values,
76                                                  GTypeCValue    *collect_values,
77                                                  guint           collect_flags);
78 static gchar*   value_param_lcopy_value         (const GValue   *value,
79                                                  guint           n_collect_values,
80                                                  GTypeCValue    *collect_values,
81                                                  guint           collect_flags);
82
83 typedef struct
84 {
85   GValue default_value;
86 } GParamSpecPrivate;
87
88 static gint g_param_private_offset;
89 #define PRIV(inst) (&G_STRUCT_MEMBER(GParamSpecPrivate, (inst), g_param_private_offset))
90
91 /* --- functions --- */
92 void
93 _g_param_type_init (void)
94 {
95   static const GTypeFundamentalInfo finfo = {
96     (G_TYPE_FLAG_CLASSED |
97      G_TYPE_FLAG_INSTANTIATABLE |
98      G_TYPE_FLAG_DERIVABLE |
99      G_TYPE_FLAG_DEEP_DERIVABLE),
100   };
101   static const GTypeValueTable param_value_table = {
102     value_param_init,           /* value_init */
103     value_param_free_value,     /* value_free */
104     value_param_copy_value,     /* value_copy */
105     value_param_peek_pointer,   /* value_peek_pointer */
106     "p",                        /* collect_format */
107     value_param_collect_value,  /* collect_value */
108     "p",                        /* lcopy_format */
109     value_param_lcopy_value,    /* lcopy_value */
110   };
111   const GTypeInfo param_spec_info = {
112     sizeof (GParamSpecClass),
113
114     (GBaseInitFunc) g_param_spec_class_base_init,
115     (GBaseFinalizeFunc) g_param_spec_class_base_finalize,
116     (GClassInitFunc) g_param_spec_class_init,
117     (GClassFinalizeFunc) NULL,
118     NULL,       /* class_data */
119
120     sizeof (GParamSpec),
121     0,          /* n_preallocs */
122     (GInstanceInitFunc) g_param_spec_init,
123
124     &param_value_table,
125   };
126   GType type;
127
128   /* This should be registered as GParamSpec instead of GParam, for
129    * consistency sake, so that type name can be mapped to struct name,
130    * However, some language bindings, most noticeable the python ones
131    * depends on the "GParam" identifier, see #548689
132    */
133   type = g_type_register_fundamental (G_TYPE_PARAM, g_intern_static_string ("GParam"), &param_spec_info, &finfo, G_TYPE_FLAG_ABSTRACT);
134   g_assert (type == G_TYPE_PARAM);
135   g_value_register_transform_func (G_TYPE_PARAM, G_TYPE_PARAM, value_param_transform_value);
136 }
137
138 static void
139 g_param_spec_class_base_init (GParamSpecClass *class)
140 {
141 }
142
143 static void
144 g_param_spec_class_base_finalize (GParamSpecClass *class)
145 {
146 }
147
148 static void
149 g_param_spec_class_init (GParamSpecClass *class,
150                          gpointer         class_data)
151 {
152   class->value_type = G_TYPE_NONE;
153   class->finalize = g_param_spec_finalize;
154   class->value_set_default = NULL;
155   class->value_validate = NULL;
156   class->values_cmp = NULL;
157
158   g_type_class_add_private (class, sizeof (GParamSpecPrivate));
159   g_param_private_offset = g_type_class_get_instance_private_offset (class);
160 }
161
162 static void
163 g_param_spec_init (GParamSpec      *pspec,
164                    GParamSpecClass *class)
165 {
166   pspec->name = NULL;
167   pspec->_nick = NULL;
168   pspec->_blurb = NULL;
169   pspec->flags = 0;
170   pspec->value_type = class->value_type;
171   pspec->owner_type = 0;
172   pspec->qdata = NULL;
173   g_datalist_set_flags (&pspec->qdata, PARAM_FLOATING_FLAG);
174   pspec->ref_count = 1;
175   pspec->param_id = 0;
176 }
177
178 static void
179 g_param_spec_finalize (GParamSpec *pspec)
180 {
181   GParamSpecPrivate *priv = PRIV (pspec);
182
183   if (priv->default_value.g_type)
184     g_value_reset (&priv->default_value);
185
186   g_datalist_clear (&pspec->qdata);
187
188   if (!(pspec->flags & G_PARAM_STATIC_NICK))
189     g_free (pspec->_nick);
190
191   if (!(pspec->flags & G_PARAM_STATIC_BLURB))
192     g_free (pspec->_blurb);
193
194   g_type_free_instance ((GTypeInstance*) pspec);
195 }
196
197 /**
198  * g_param_spec_ref: (skip)
199  * @pspec: a valid #GParamSpec
200  *
201  * Increments the reference count of @pspec.
202  *
203  * Returns: the #GParamSpec that was passed into this function
204  */
205 GParamSpec*
206 g_param_spec_ref (GParamSpec *pspec)
207 {
208   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
209
210   g_atomic_int_inc ((int *)&pspec->ref_count);
211
212   return pspec;
213 }
214
215 /**
216  * g_param_spec_unref: (skip)
217  * @pspec: a valid #GParamSpec
218  *
219  * Decrements the reference count of a @pspec.
220  */
221 void
222 g_param_spec_unref (GParamSpec *pspec)
223 {
224   gboolean is_zero;
225
226   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
227
228   is_zero = g_atomic_int_dec_and_test ((int *)&pspec->ref_count);
229
230   if (G_UNLIKELY (is_zero))
231     {
232       G_PARAM_SPEC_GET_CLASS (pspec)->finalize (pspec);
233     }
234 }
235
236 /**
237  * g_param_spec_sink:
238  * @pspec: a valid #GParamSpec
239  *
240  * The initial reference count of a newly created #GParamSpec is 1,
241  * even though no one has explicitly called g_param_spec_ref() on it
242  * yet. So the initial reference count is flagged as "floating", until
243  * someone calls <literal>g_param_spec_ref (pspec); g_param_spec_sink
244  * (pspec);</literal> in sequence on it, taking over the initial
245  * reference count (thus ending up with a @pspec that has a reference
246  * count of 1 still, but is not flagged "floating" anymore).
247  */
248 void
249 g_param_spec_sink (GParamSpec *pspec)
250 {
251   gsize oldvalue;
252   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
253
254   oldvalue = g_atomic_pointer_and (&pspec->qdata, ~(gsize)PARAM_FLOATING_FLAG);
255   if (oldvalue & PARAM_FLOATING_FLAG)
256     g_param_spec_unref (pspec);
257 }
258
259 /**
260  * g_param_spec_ref_sink: (skip)
261  * @pspec: a valid #GParamSpec
262  *
263  * Convenience function to ref and sink a #GParamSpec.
264  *
265  * Since: 2.10
266  * Returns: the #GParamSpec that was passed into this function
267  */
268 GParamSpec*
269 g_param_spec_ref_sink (GParamSpec *pspec)
270 {
271   gsize oldvalue;
272   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
273
274   oldvalue = g_atomic_pointer_and (&pspec->qdata, ~(gsize)PARAM_FLOATING_FLAG);
275   if (!(oldvalue & PARAM_FLOATING_FLAG))
276     g_param_spec_ref (pspec);
277
278   return pspec;
279 }
280
281 /**
282  * g_param_spec_get_name:
283  * @pspec: a valid #GParamSpec
284  *
285  * Get the name of a #GParamSpec.
286  *
287  * The name is always an "interned" string (as per g_intern_string()).
288  * This allows for pointer-value comparisons.
289  *
290  * Returns: the name of @pspec.
291  */
292 const gchar *
293 g_param_spec_get_name (GParamSpec *pspec)
294 {
295   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
296
297   return pspec->name;
298 }
299
300 /**
301  * g_param_spec_get_nick:
302  * @pspec: a valid #GParamSpec
303  *
304  * Get the nickname of a #GParamSpec.
305  *
306  * Returns: the nickname of @pspec.
307  */
308 const gchar *
309 g_param_spec_get_nick (GParamSpec *pspec)
310 {
311   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
312
313   if (pspec->_nick)
314     return pspec->_nick;
315   else
316     {
317       GParamSpec *redirect_target;
318
319       redirect_target = g_param_spec_get_redirect_target (pspec);
320       if (redirect_target && redirect_target->_nick)
321         return redirect_target->_nick;
322     }
323
324   return pspec->name;
325 }
326
327 /**
328  * g_param_spec_get_blurb:
329  * @pspec: a valid #GParamSpec
330  *
331  * Get the short description of a #GParamSpec.
332  *
333  * Returns: the short description of @pspec.
334  */
335 const gchar *
336 g_param_spec_get_blurb (GParamSpec *pspec)
337 {
338   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
339
340   if (pspec->_blurb)
341     return pspec->_blurb;
342   else
343     {
344       GParamSpec *redirect_target;
345
346       redirect_target = g_param_spec_get_redirect_target (pspec);
347       if (redirect_target && redirect_target->_blurb)
348         return redirect_target->_blurb;
349     }
350
351   return NULL;
352 }
353
354 static void
355 canonicalize_key (gchar *key)
356 {
357   gchar *p;
358   
359   for (p = key; *p != 0; p++)
360     {
361       gchar c = *p;
362       
363       if (c != '-' &&
364           (c < '0' || c > '9') &&
365           (c < 'A' || c > 'Z') &&
366           (c < 'a' || c > 'z'))
367         *p = '-';
368     }
369 }
370
371 static gboolean
372 is_canonical (const gchar *key)
373 {
374   const gchar *p;
375
376   for (p = key; *p != 0; p++)
377     {
378       gchar c = *p;
379       
380       if (c != '-' &&
381           (c < '0' || c > '9') &&
382           (c < 'A' || c > 'Z') &&
383           (c < 'a' || c > 'z'))
384         return FALSE;
385     }
386
387   return TRUE;
388 }
389
390 /**
391  * g_param_spec_internal: (skip)
392  * @param_type: the #GType for the property; must be derived from #G_TYPE_PARAM
393  * @name: the canonical name of the property
394  * @nick: the nickname of the property
395  * @blurb: a short description of the property
396  * @flags: a combination of #GParamFlags
397  *
398  * Creates a new #GParamSpec instance.
399  *
400  * A property name consists of segments consisting of ASCII letters and
401  * digits, separated by either the '-' or '_' character. The first
402  * character of a property name must be a letter. Names which violate these
403  * rules lead to undefined behaviour.
404  *
405  * When creating and looking up a #GParamSpec, either separator can be
406  * used, but they cannot be mixed. Using '-' is considerably more
407  * efficient and in fact required when using property names as detail
408  * strings for signals.
409  *
410  * Beyond the name, #GParamSpec<!-- -->s have two more descriptive
411  * strings associated with them, the @nick, which should be suitable
412  * for use as a label for the property in a property editor, and the
413  * @blurb, which should be a somewhat longer description, suitable for
414  * e.g. a tooltip. The @nick and @blurb should ideally be localized.
415  *
416  * Returns: a newly allocated #GParamSpec instance
417  */
418 gpointer
419 g_param_spec_internal (GType        param_type,
420                        const gchar *name,
421                        const gchar *nick,
422                        const gchar *blurb,
423                        GParamFlags  flags)
424 {
425   GParamSpec *pspec;
426   
427   g_return_val_if_fail (G_TYPE_IS_PARAM (param_type) && param_type != G_TYPE_PARAM, NULL);
428   g_return_val_if_fail (name != NULL, NULL);
429   g_return_val_if_fail ((name[0] >= 'A' && name[0] <= 'Z') || (name[0] >= 'a' && name[0] <= 'z'), NULL);
430   g_return_val_if_fail (!(flags & G_PARAM_STATIC_NAME) || is_canonical (name), NULL);
431   
432   pspec = (gpointer) g_type_create_instance (param_type);
433
434   if (flags & G_PARAM_STATIC_NAME)
435     {
436       /* pspec->name is not freed if (flags & G_PARAM_STATIC_NAME) */
437       pspec->name = (gchar *) g_intern_static_string (name);
438       if (!is_canonical (pspec->name))
439         g_warning ("G_PARAM_STATIC_NAME used with non-canonical pspec name: %s", pspec->name);
440     }
441   else
442     {
443       if (is_canonical (name))
444         pspec->name = (gchar *) g_intern_string (name);
445       else
446         {
447           gchar *tmp = g_strdup (name);
448           canonicalize_key (tmp);
449           pspec->name = (gchar *) g_intern_string (tmp);
450           g_free (tmp);
451         }
452     }
453
454   if (flags & G_PARAM_STATIC_NICK)
455     pspec->_nick = (gchar*) nick;
456   else
457     pspec->_nick = g_strdup (nick);
458
459   if (flags & G_PARAM_STATIC_BLURB)
460     pspec->_blurb = (gchar*) blurb;
461   else
462     pspec->_blurb = g_strdup (blurb);
463
464   pspec->flags = (flags & G_PARAM_USER_MASK) | (flags & G_PARAM_MASK);
465   
466   return pspec;
467 }
468
469 /**
470  * g_param_spec_get_qdata:
471  * @pspec: a valid #GParamSpec
472  * @quark: a #GQuark, naming the user data pointer
473  *
474  * Gets back user data pointers stored via g_param_spec_set_qdata().
475  *
476  * Returns: (transfer none): the user data pointer set, or %NULL
477  */
478 gpointer
479 g_param_spec_get_qdata (GParamSpec *pspec,
480                         GQuark      quark)
481 {
482   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
483   
484   return quark ? g_datalist_id_get_data (&pspec->qdata, quark) : NULL;
485 }
486
487 /**
488  * g_param_spec_set_qdata:
489  * @pspec: the #GParamSpec to set store a user data pointer
490  * @quark: a #GQuark, naming the user data pointer
491  * @data: an opaque user data pointer
492  *
493  * Sets an opaque, named pointer on a #GParamSpec. The name is
494  * specified through a #GQuark (retrieved e.g. via
495  * g_quark_from_static_string()), and the pointer can be gotten back
496  * from the @pspec with g_param_spec_get_qdata().  Setting a
497  * previously set user data pointer, overrides (frees) the old pointer
498  * set, using %NULL as pointer essentially removes the data stored.
499  */
500 void
501 g_param_spec_set_qdata (GParamSpec *pspec,
502                         GQuark      quark,
503                         gpointer    data)
504 {
505   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
506   g_return_if_fail (quark > 0);
507
508   g_datalist_id_set_data (&pspec->qdata, quark, data);
509 }
510
511 /**
512  * g_param_spec_set_qdata_full: (skip)
513  * @pspec: the #GParamSpec to set store a user data pointer
514  * @quark: a #GQuark, naming the user data pointer
515  * @data: an opaque user data pointer
516  * @destroy: function to invoke with @data as argument, when @data needs to
517  *  be freed
518  *
519  * This function works like g_param_spec_set_qdata(), but in addition,
520  * a <literal>void (*destroy) (gpointer)</literal> function may be
521  * specified which is called with @data as argument when the @pspec is
522  * finalized, or the data is being overwritten by a call to
523  * g_param_spec_set_qdata() with the same @quark.
524  */
525 void
526 g_param_spec_set_qdata_full (GParamSpec    *pspec,
527                              GQuark         quark,
528                              gpointer       data,
529                              GDestroyNotify destroy)
530 {
531   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
532   g_return_if_fail (quark > 0);
533
534   g_datalist_id_set_data_full (&pspec->qdata, quark, data, data ? destroy : (GDestroyNotify) NULL);
535 }
536
537 /**
538  * g_param_spec_steal_qdata:
539  * @pspec: the #GParamSpec to get a stored user data pointer from
540  * @quark: a #GQuark, naming the user data pointer
541  *
542  * Gets back user data pointers stored via g_param_spec_set_qdata()
543  * and removes the @data from @pspec without invoking its destroy()
544  * function (if any was set).  Usually, calling this function is only
545  * required to update user data pointers with a destroy notifier.
546  *
547  * Returns: (transfer none): the user data pointer set, or %NULL
548  */
549 gpointer
550 g_param_spec_steal_qdata (GParamSpec *pspec,
551                           GQuark      quark)
552 {
553   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
554   g_return_val_if_fail (quark > 0, NULL);
555   
556   return g_datalist_id_remove_no_notify (&pspec->qdata, quark);
557 }
558
559 /**
560  * g_param_spec_get_redirect_target:
561  * @pspec: a #GParamSpec
562  *
563  * If the paramspec redirects operations to another paramspec,
564  * returns that paramspec. Redirect is used typically for
565  * providing a new implementation of a property in a derived
566  * type while preserving all the properties from the parent
567  * type. Redirection is established by creating a property
568  * of type #GParamSpecOverride. See g_object_class_override_property()
569  * for an example of the use of this capability.
570  *
571  * Since: 2.4
572  *
573  * Returns: (transfer none): paramspec to which requests on this
574  *          paramspec should be redirected, or %NULL if none.
575  */
576 GParamSpec*
577 g_param_spec_get_redirect_target (GParamSpec *pspec)
578 {
579   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
580
581   if (G_IS_PARAM_SPEC_OVERRIDE (pspec))
582     {
583       GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
584
585       return ospec->overridden;
586     }
587   else
588     return NULL;
589 }
590
591 /**
592  * g_param_value_set_default:
593  * @pspec: a valid #GParamSpec
594  * @value: a #GValue of correct type for @pspec
595  *
596  * Sets @value to its default value as specified in @pspec.
597  */
598 void
599 g_param_value_set_default (GParamSpec *pspec,
600                            GValue     *value)
601 {
602   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
603   g_return_if_fail (G_IS_VALUE (value));
604   g_return_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value));
605
606   g_value_reset (value);
607   G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, value);
608 }
609
610 /**
611  * g_param_value_defaults:
612  * @pspec: a valid #GParamSpec
613  * @value: a #GValue of correct type for @pspec
614  *
615  * Checks whether @value contains the default value as specified in @pspec.
616  *
617  * Returns: whether @value contains the canonical default for this @pspec
618  */
619 gboolean
620 g_param_value_defaults (GParamSpec *pspec,
621                         GValue     *value)
622 {
623   GValue dflt_value = G_VALUE_INIT;
624   gboolean defaults;
625
626   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
627   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
628   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE);
629
630   g_value_init (&dflt_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
631   G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, &dflt_value);
632   defaults = G_PARAM_SPEC_GET_CLASS (pspec)->values_cmp (pspec, value, &dflt_value) == 0;
633   g_value_unset (&dflt_value);
634
635   return defaults;
636 }
637
638 /**
639  * g_param_value_validate:
640  * @pspec: a valid #GParamSpec
641  * @value: a #GValue of correct type for @pspec
642  *
643  * Ensures that the contents of @value comply with the specifications
644  * set out by @pspec. For example, a #GParamSpecInt might require
645  * that integers stored in @value may not be smaller than -42 and not be
646  * greater than +42. If @value contains an integer outside of this range,
647  * it is modified accordingly, so the resulting value will fit into the
648  * range -42 .. +42.
649  *
650  * Returns: whether modifying @value was necessary to ensure validity
651  */
652 gboolean
653 g_param_value_validate (GParamSpec *pspec,
654                         GValue     *value)
655 {
656   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
657   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
658   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE);
659
660   if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate)
661     {
662       GValue oval = *value;
663
664       if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate (pspec, value) ||
665           memcmp (&oval.data, &value->data, sizeof (oval.data)))
666         return TRUE;
667     }
668
669   return FALSE;
670 }
671
672 /**
673  * g_param_value_convert:
674  * @pspec: a valid #GParamSpec
675  * @src_value: souce #GValue
676  * @dest_value: destination #GValue of correct type for @pspec
677  * @strict_validation: %TRUE requires @dest_value to conform to @pspec
678  * without modifications
679  *
680  * Transforms @src_value into @dest_value if possible, and then
681  * validates @dest_value, in order for it to conform to @pspec.  If
682  * @strict_validation is %TRUE this function will only succeed if the
683  * transformed @dest_value complied to @pspec without modifications.
684  *
685  * See also g_value_type_transformable(), g_value_transform() and
686  * g_param_value_validate().
687  *
688  * Returns: %TRUE if transformation and validation were successful,
689  *  %FALSE otherwise and @dest_value is left untouched.
690  */
691 gboolean
692 g_param_value_convert (GParamSpec   *pspec,
693                        const GValue *src_value,
694                        GValue       *dest_value,
695                        gboolean      strict_validation)
696 {
697   GValue tmp_value = G_VALUE_INIT;
698
699   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
700   g_return_val_if_fail (G_IS_VALUE (src_value), FALSE);
701   g_return_val_if_fail (G_IS_VALUE (dest_value), FALSE);
702   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, dest_value), FALSE);
703
704   /* better leave dest_value untouched when returning FALSE */
705
706   g_value_init (&tmp_value, G_VALUE_TYPE (dest_value));
707   if (g_value_transform (src_value, &tmp_value) &&
708       (!g_param_value_validate (pspec, &tmp_value) || !strict_validation))
709     {
710       g_value_unset (dest_value);
711       
712       /* values are relocatable */
713       memcpy (dest_value, &tmp_value, sizeof (tmp_value));
714       
715       return TRUE;
716     }
717   else
718     {
719       g_value_unset (&tmp_value);
720       
721       return FALSE;
722     }
723 }
724
725 /**
726  * g_param_values_cmp:
727  * @pspec: a valid #GParamSpec
728  * @value1: a #GValue of correct type for @pspec
729  * @value2: a #GValue of correct type for @pspec
730  *
731  * Compares @value1 with @value2 according to @pspec, and return -1, 0 or +1,
732  * if @value1 is found to be less than, equal to or greater than @value2,
733  * respectively.
734  *
735  * Returns: -1, 0 or +1, for a less than, equal to or greater than result
736  */
737 gint
738 g_param_values_cmp (GParamSpec   *pspec,
739                     const GValue *value1,
740                     const GValue *value2)
741 {
742   gint cmp;
743
744   /* param_values_cmp() effectively does: value1 - value2
745    * so the return values are:
746    * -1)  value1 < value2
747    *  0)  value1 == value2
748    *  1)  value1 > value2
749    */
750   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), 0);
751   g_return_val_if_fail (G_IS_VALUE (value1), 0);
752   g_return_val_if_fail (G_IS_VALUE (value2), 0);
753   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value1), 0);
754   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value2), 0);
755
756   cmp = G_PARAM_SPEC_GET_CLASS (pspec)->values_cmp (pspec, value1, value2);
757
758   return CLAMP (cmp, -1, 1);
759 }
760
761 static void
762 value_param_init (GValue *value)
763 {
764   value->data[0].v_pointer = NULL;
765 }
766
767 static void
768 value_param_free_value (GValue *value)
769 {
770   if (value->data[0].v_pointer)
771     g_param_spec_unref (value->data[0].v_pointer);
772 }
773
774 static void
775 value_param_copy_value (const GValue *src_value,
776                         GValue       *dest_value)
777 {
778   if (src_value->data[0].v_pointer)
779     dest_value->data[0].v_pointer = g_param_spec_ref (src_value->data[0].v_pointer);
780   else
781     dest_value->data[0].v_pointer = NULL;
782 }
783
784 static void
785 value_param_transform_value (const GValue *src_value,
786                              GValue       *dest_value)
787 {
788   if (src_value->data[0].v_pointer &&
789       g_type_is_a (G_PARAM_SPEC_TYPE (dest_value->data[0].v_pointer), G_VALUE_TYPE (dest_value)))
790     dest_value->data[0].v_pointer = g_param_spec_ref (src_value->data[0].v_pointer);
791   else
792     dest_value->data[0].v_pointer = NULL;
793 }
794
795 static gpointer
796 value_param_peek_pointer (const GValue *value)
797 {
798   return value->data[0].v_pointer;
799 }
800
801 static gchar*
802 value_param_collect_value (GValue      *value,
803                            guint        n_collect_values,
804                            GTypeCValue *collect_values,
805                            guint        collect_flags)
806 {
807   if (collect_values[0].v_pointer)
808     {
809       GParamSpec *param = collect_values[0].v_pointer;
810
811       if (param->g_type_instance.g_class == NULL)
812         return g_strconcat ("invalid unclassed param spec pointer for value type `",
813                             G_VALUE_TYPE_NAME (value),
814                             "'",
815                             NULL);
816       else if (!g_value_type_compatible (G_PARAM_SPEC_TYPE (param), G_VALUE_TYPE (value)))
817         return g_strconcat ("invalid param spec type `",
818                             G_PARAM_SPEC_TYPE_NAME (param),
819                             "' for value type `",
820                             G_VALUE_TYPE_NAME (value),
821                             "'",
822                             NULL);
823       value->data[0].v_pointer = g_param_spec_ref (param);
824     }
825   else
826     value->data[0].v_pointer = NULL;
827
828   return NULL;
829 }
830
831 static gchar*
832 value_param_lcopy_value (const GValue *value,
833                          guint         n_collect_values,
834                          GTypeCValue  *collect_values,
835                          guint         collect_flags)
836 {
837   GParamSpec **param_p = collect_values[0].v_pointer;
838
839   if (!param_p)
840     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
841
842   if (!value->data[0].v_pointer)
843     *param_p = NULL;
844   else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
845     *param_p = value->data[0].v_pointer;
846   else
847     *param_p = g_param_spec_ref (value->data[0].v_pointer);
848
849   return NULL;
850 }
851
852
853 /* --- param spec pool --- */
854 /**
855  * GParamSpecPool:
856  *
857  * A #GParamSpecPool maintains a collection of #GParamSpec<!-- -->s which can be
858  * quickly accessed by owner and name. The implementation of the #GObject property
859  * system uses such a pool to store the #GParamSpecs of the properties all object
860  * types.
861  */
862 struct _GParamSpecPool
863 {
864   GMutex       mutex;
865   gboolean     type_prefixing;
866   GHashTable  *hash_table;
867 };
868
869 static guint
870 param_spec_pool_hash (gconstpointer key_spec)
871 {
872   const GParamSpec *key = key_spec;
873   const gchar *p;
874   guint h = key->owner_type;
875
876   for (p = key->name; *p; p++)
877     h = (h << 5) - h + *p;
878
879   return h;
880 }
881
882 static gboolean
883 param_spec_pool_equals (gconstpointer key_spec_1,
884                         gconstpointer key_spec_2)
885 {
886   const GParamSpec *key1 = key_spec_1;
887   const GParamSpec *key2 = key_spec_2;
888
889   return (key1->owner_type == key2->owner_type &&
890           strcmp (key1->name, key2->name) == 0);
891 }
892
893 /**
894  * g_param_spec_pool_new:
895  * @type_prefixing: Whether the pool will support type-prefixed property names.
896  *
897  * Creates a new #GParamSpecPool.
898  *
899  * If @type_prefixing is %TRUE, lookups in the newly created pool will
900  * allow to specify the owner as a colon-separated prefix of the
901  * property name, like "GtkContainer:border-width". This feature is
902  * deprecated, so you should always set @type_prefixing to %FALSE.
903  *
904  * Returns: (transfer none): a newly allocated #GParamSpecPool.
905  */
906 GParamSpecPool*
907 g_param_spec_pool_new (gboolean type_prefixing)
908 {
909   static GMutex init_mutex;
910   GParamSpecPool *pool = g_new (GParamSpecPool, 1);
911
912   memcpy (&pool->mutex, &init_mutex, sizeof (init_mutex));
913   pool->type_prefixing = type_prefixing != FALSE;
914   pool->hash_table = g_hash_table_new (param_spec_pool_hash, param_spec_pool_equals);
915
916   return pool;
917 }
918
919 /**
920  * g_param_spec_pool_insert:
921  * @pool: a #GParamSpecPool.
922  * @pspec: the #GParamSpec to insert
923  * @owner_type: a #GType identifying the owner of @pspec
924  *
925  * Inserts a #GParamSpec in the pool.
926  */
927 void
928 g_param_spec_pool_insert (GParamSpecPool *pool,
929                           GParamSpec     *pspec,
930                           GType           owner_type)
931 {
932   const gchar *p;
933   
934   if (pool && pspec && owner_type > 0 && pspec->owner_type == 0)
935     {
936       for (p = pspec->name; *p; p++)
937         {
938           if (!strchr (G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-_", *p))
939             {
940               g_warning (G_STRLOC ": pspec name \"%s\" contains invalid characters", pspec->name);
941               return;
942             }
943         }
944       g_mutex_lock (&pool->mutex);
945       pspec->owner_type = owner_type;
946       g_param_spec_ref (pspec);
947       g_hash_table_insert (pool->hash_table, pspec, pspec);
948       g_mutex_unlock (&pool->mutex);
949     }
950   else
951     {
952       g_return_if_fail (pool != NULL);
953       g_return_if_fail (pspec);
954       g_return_if_fail (owner_type > 0);
955       g_return_if_fail (pspec->owner_type == 0);
956     }
957 }
958
959 /**
960  * g_param_spec_pool_remove:
961  * @pool: a #GParamSpecPool
962  * @pspec: the #GParamSpec to remove
963  *
964  * Removes a #GParamSpec from the pool.
965  */
966 void
967 g_param_spec_pool_remove (GParamSpecPool *pool,
968                           GParamSpec     *pspec)
969 {
970   if (pool && pspec)
971     {
972       g_mutex_lock (&pool->mutex);
973       if (g_hash_table_remove (pool->hash_table, pspec))
974         g_param_spec_unref (pspec);
975       else
976         g_warning (G_STRLOC ": attempt to remove unknown pspec `%s' from pool", pspec->name);
977       g_mutex_unlock (&pool->mutex);
978     }
979   else
980     {
981       g_return_if_fail (pool != NULL);
982       g_return_if_fail (pspec);
983     }
984 }
985
986 static inline GParamSpec*
987 param_spec_ht_lookup (GHashTable  *hash_table,
988                       const gchar *param_name,
989                       GType        owner_type,
990                       gboolean     walk_ancestors)
991 {
992   GParamSpec key, *pspec;
993
994   key.owner_type = owner_type;
995   key.name = (gchar*) param_name;
996   if (walk_ancestors)
997     do
998       {
999         pspec = g_hash_table_lookup (hash_table, &key);
1000         if (pspec)
1001           return pspec;
1002         key.owner_type = g_type_parent (key.owner_type);
1003       }
1004     while (key.owner_type);
1005   else
1006     pspec = g_hash_table_lookup (hash_table, &key);
1007
1008   if (!pspec && !is_canonical (param_name))
1009     {
1010       gchar *canonical;
1011
1012       canonical = g_strdup (key.name);
1013       canonicalize_key (canonical);
1014
1015       /* try canonicalized form */
1016       key.name = canonical;
1017       key.owner_type = owner_type;
1018
1019       if (walk_ancestors)
1020         do
1021           {
1022             pspec = g_hash_table_lookup (hash_table, &key);
1023             if (pspec)
1024               {
1025                 g_free (canonical);
1026                 return pspec;
1027               }
1028             key.owner_type = g_type_parent (key.owner_type);
1029           }
1030         while (key.owner_type);
1031       else
1032         pspec = g_hash_table_lookup (hash_table, &key);
1033
1034       g_free (canonical);
1035     }
1036
1037   return pspec;
1038 }
1039
1040 /**
1041  * g_param_spec_pool_lookup:
1042  * @pool: a #GParamSpecPool
1043  * @param_name: the name to look for
1044  * @owner_type: the owner to look for
1045  * @walk_ancestors: If %TRUE, also try to find a #GParamSpec with @param_name
1046  *  owned by an ancestor of @owner_type.
1047  *
1048  * Looks up a #GParamSpec in the pool.
1049  *
1050  * Returns: (transfer none): The found #GParamSpec, or %NULL if no
1051  * matching #GParamSpec was found.
1052  */
1053 GParamSpec*
1054 g_param_spec_pool_lookup (GParamSpecPool *pool,
1055                           const gchar    *param_name,
1056                           GType           owner_type,
1057                           gboolean        walk_ancestors)
1058 {
1059   GParamSpec *pspec;
1060   gchar *delim;
1061
1062   if (!pool || !param_name)
1063     {
1064       g_return_val_if_fail (pool != NULL, NULL);
1065       g_return_val_if_fail (param_name != NULL, NULL);
1066     }
1067
1068   g_mutex_lock (&pool->mutex);
1069
1070   delim = pool->type_prefixing ? strchr (param_name, ':') : NULL;
1071
1072   /* try quick and away, i.e. without prefix */
1073   if (!delim)
1074     {
1075       pspec = param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
1076       g_mutex_unlock (&pool->mutex);
1077
1078       return pspec;
1079     }
1080
1081   /* strip type prefix */
1082   if (pool->type_prefixing && delim[1] == ':')
1083     {
1084       guint l = delim - param_name;
1085       gchar stack_buffer[32], *buffer = l < 32 ? stack_buffer : g_new (gchar, l + 1);
1086       GType type;
1087       
1088       strncpy (buffer, param_name, delim - param_name);
1089       buffer[l] = 0;
1090       type = g_type_from_name (buffer);
1091       if (l >= 32)
1092         g_free (buffer);
1093       if (type)         /* type==0 isn't a valid type pefix */
1094         {
1095           /* sanity check, these cases don't make a whole lot of sense */
1096           if ((!walk_ancestors && type != owner_type) || !g_type_is_a (owner_type, type))
1097             {
1098               g_mutex_unlock (&pool->mutex);
1099
1100               return NULL;
1101             }
1102           owner_type = type;
1103           param_name += l + 2;
1104           pspec = param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
1105           g_mutex_unlock (&pool->mutex);
1106
1107           return pspec;
1108         }
1109     }
1110   /* malformed param_name */
1111
1112   g_mutex_unlock (&pool->mutex);
1113
1114   return NULL;
1115 }
1116
1117 static void
1118 pool_list (gpointer key,
1119            gpointer value,
1120            gpointer user_data)
1121 {
1122   GParamSpec *pspec = value;
1123   gpointer *data = user_data;
1124   GType owner_type = (GType) data[1];
1125
1126   if (owner_type == pspec->owner_type)
1127     data[0] = g_list_prepend (data[0], pspec);
1128 }
1129
1130 /**
1131  * g_param_spec_pool_list_owned:
1132  * @pool: a #GParamSpecPool
1133  * @owner_type: the owner to look for
1134  *
1135  * Gets an #GList of all #GParamSpec<!-- -->s owned by @owner_type in
1136  * the pool.
1137  *
1138  * Returns: (transfer container) (element-type GObject.ParamSpec): a
1139  *          #GList of all #GParamSpec<!-- -->s owned by @owner_type in
1140  *          the pool#GParamSpec<!-- -->s.
1141  */
1142 GList*
1143 g_param_spec_pool_list_owned (GParamSpecPool *pool,
1144                               GType           owner_type)
1145 {
1146   gpointer data[2];
1147
1148   g_return_val_if_fail (pool != NULL, NULL);
1149   g_return_val_if_fail (owner_type > 0, NULL);
1150   
1151   g_mutex_lock (&pool->mutex);
1152   data[0] = NULL;
1153   data[1] = (gpointer) owner_type;
1154   g_hash_table_foreach (pool->hash_table, pool_list, &data);
1155   g_mutex_unlock (&pool->mutex);
1156
1157   return data[0];
1158 }
1159
1160 static gint
1161 pspec_compare_id (gconstpointer a,
1162                   gconstpointer b)
1163 {
1164   const GParamSpec *pspec1 = a, *pspec2 = b;
1165
1166   if (pspec1->param_id < pspec2->param_id)
1167     return -1;
1168
1169   if (pspec1->param_id > pspec2->param_id)
1170     return 1;
1171
1172   return strcmp (pspec1->name, pspec2->name);
1173 }
1174
1175 static inline GSList*
1176 pspec_list_remove_overridden_and_redirected (GSList     *plist,
1177                                              GHashTable *ht,
1178                                              GType       owner_type,
1179                                              guint      *n_p)
1180 {
1181   GSList *rlist = NULL;
1182
1183   while (plist)
1184     {
1185       GSList *tmp = plist->next;
1186       GParamSpec *pspec = plist->data;
1187       GParamSpec *found;
1188       gboolean remove = FALSE;
1189
1190       /* Remove paramspecs that are redirected, and also paramspecs
1191        * that have are overridden by non-redirected properties.
1192        * The idea is to get the single paramspec for each name that
1193        * best corresponds to what the application sees.
1194        */
1195       if (g_param_spec_get_redirect_target (pspec))
1196         remove = TRUE;
1197       else
1198         {
1199           found = param_spec_ht_lookup (ht, pspec->name, owner_type, TRUE);
1200           if (found != pspec)
1201             {
1202               GParamSpec *redirect = g_param_spec_get_redirect_target (found);
1203               if (redirect != pspec)
1204                 remove = TRUE;
1205             }
1206         }
1207
1208       if (remove)
1209         {
1210           g_slist_free_1 (plist);
1211         }
1212       else
1213         {
1214           plist->next = rlist;
1215           rlist = plist;
1216           *n_p += 1;
1217         }
1218       plist = tmp;
1219     }
1220   return rlist;
1221 }
1222
1223 static void
1224 pool_depth_list (gpointer key,
1225                  gpointer value,
1226                  gpointer user_data)
1227 {
1228   GParamSpec *pspec = value;
1229   gpointer *data = user_data;
1230   GSList **slists = data[0];
1231   GType owner_type = (GType) data[1];
1232
1233   if (g_type_is_a (owner_type, pspec->owner_type))
1234     {
1235       if (G_TYPE_IS_INTERFACE (pspec->owner_type))
1236         {
1237           slists[0] = g_slist_prepend (slists[0], pspec);
1238         }
1239       else
1240         {
1241           guint d = g_type_depth (pspec->owner_type);
1242
1243           slists[d - 1] = g_slist_prepend (slists[d - 1], pspec);
1244         }
1245     }
1246 }
1247
1248 /* We handle interfaces specially since we don't want to
1249  * count interface prerequisites like normal inheritance;
1250  * the property comes from the direct inheritance from
1251  * the prerequisite class, not from the interface that
1252  * prerequires it.
1253  * 
1254  * also 'depth' isn't a meaningful concept for interface
1255  * prerequites.
1256  */
1257 static void
1258 pool_depth_list_for_interface (gpointer key,
1259                                gpointer value,
1260                                gpointer user_data)
1261 {
1262   GParamSpec *pspec = value;
1263   gpointer *data = user_data;
1264   GSList **slists = data[0];
1265   GType owner_type = (GType) data[1];
1266
1267   if (pspec->owner_type == owner_type)
1268     slists[0] = g_slist_prepend (slists[0], pspec);
1269 }
1270
1271 /**
1272  * g_param_spec_pool_list:
1273  * @pool: a #GParamSpecPool
1274  * @owner_type: the owner to look for
1275  * @n_pspecs_p: (out): return location for the length of the returned array
1276  *
1277  * Gets an array of all #GParamSpec<!-- -->s owned by @owner_type in
1278  * the pool.
1279  *
1280  * Returns: (array length=n_pspecs_p) (transfer container): a newly
1281  *          allocated array containing pointers to all #GParamSpecs
1282  *          owned by @owner_type in the pool
1283  */
1284 GParamSpec**
1285 g_param_spec_pool_list (GParamSpecPool *pool,
1286                         GType           owner_type,
1287                         guint          *n_pspecs_p)
1288 {
1289   GParamSpec **pspecs, **p;
1290   GSList **slists, *node;
1291   gpointer data[2];
1292   guint d, i;
1293
1294   g_return_val_if_fail (pool != NULL, NULL);
1295   g_return_val_if_fail (owner_type > 0, NULL);
1296   g_return_val_if_fail (n_pspecs_p != NULL, NULL);
1297   
1298   g_mutex_lock (&pool->mutex);
1299   *n_pspecs_p = 0;
1300   d = g_type_depth (owner_type);
1301   slists = g_new0 (GSList*, d);
1302   data[0] = slists;
1303   data[1] = (gpointer) owner_type;
1304
1305   g_hash_table_foreach (pool->hash_table,
1306                         G_TYPE_IS_INTERFACE (owner_type) ?
1307                            pool_depth_list_for_interface :
1308                            pool_depth_list,
1309                         &data);
1310   
1311   for (i = 0; i < d; i++)
1312     slists[i] = pspec_list_remove_overridden_and_redirected (slists[i], pool->hash_table, owner_type, n_pspecs_p);
1313   pspecs = g_new (GParamSpec*, *n_pspecs_p + 1);
1314   p = pspecs;
1315   for (i = 0; i < d; i++)
1316     {
1317       slists[i] = g_slist_sort (slists[i], pspec_compare_id);
1318       for (node = slists[i]; node; node = node->next)
1319         *p++ = node->data;
1320       g_slist_free (slists[i]);
1321     }
1322   *p++ = NULL;
1323   g_free (slists);
1324   g_mutex_unlock (&pool->mutex);
1325
1326   return pspecs;
1327 }
1328
1329
1330 /* --- auxiliary functions --- */
1331 typedef struct
1332 {
1333   /* class portion */
1334   GType           value_type;
1335   void          (*finalize)             (GParamSpec   *pspec);
1336   void          (*value_set_default)    (GParamSpec   *pspec,
1337                                          GValue       *value);
1338   gboolean      (*value_validate)       (GParamSpec   *pspec,
1339                                          GValue       *value);
1340   gint          (*values_cmp)           (GParamSpec   *pspec,
1341                                          const GValue *value1,
1342                                          const GValue *value2);
1343 } ParamSpecClassInfo;
1344
1345 static void
1346 param_spec_generic_class_init (gpointer g_class,
1347                                gpointer class_data)
1348 {
1349   GParamSpecClass *class = g_class;
1350   ParamSpecClassInfo *info = class_data;
1351
1352   class->value_type = info->value_type;
1353   if (info->finalize)
1354     class->finalize = info->finalize;                   /* optional */
1355   class->value_set_default = info->value_set_default;
1356   if (info->value_validate)
1357     class->value_validate = info->value_validate;       /* optional */
1358   class->values_cmp = info->values_cmp;
1359   g_free (class_data);
1360 }
1361
1362 static void
1363 default_value_set_default (GParamSpec *pspec,
1364                            GValue     *value)
1365 {
1366   /* value is already zero initialized */
1367 }
1368
1369 static gint
1370 default_values_cmp (GParamSpec   *pspec,
1371                     const GValue *value1,
1372                     const GValue *value2)
1373 {
1374   return memcmp (&value1->data, &value2->data, sizeof (value1->data));
1375 }
1376
1377 /**
1378  * g_param_type_register_static:
1379  * @name: 0-terminated string used as the name of the new #GParamSpec type.
1380  * @pspec_info: The #GParamSpecTypeInfo for this #GParamSpec type.
1381  *
1382  * Registers @name as the name of a new static type derived from
1383  * #G_TYPE_PARAM. The type system uses the information contained in
1384  * the #GParamSpecTypeInfo structure pointed to by @info to manage the
1385  * #GParamSpec type and its instances.
1386  *
1387  * Returns: The new type identifier.
1388  */
1389 GType
1390 g_param_type_register_static (const gchar              *name,
1391                               const GParamSpecTypeInfo *pspec_info)
1392 {
1393   GTypeInfo info = {
1394     sizeof (GParamSpecClass),      /* class_size */
1395     NULL,                          /* base_init */
1396     NULL,                          /* base_destroy */
1397     param_spec_generic_class_init, /* class_init */
1398     NULL,                          /* class_destroy */
1399     NULL,                          /* class_data */
1400     0,                             /* instance_size */
1401     16,                            /* n_preallocs */
1402     NULL,                          /* instance_init */
1403   };
1404   ParamSpecClassInfo *cinfo;
1405
1406   g_return_val_if_fail (name != NULL, 0);
1407   g_return_val_if_fail (pspec_info != NULL, 0);
1408   g_return_val_if_fail (g_type_from_name (name) == 0, 0);
1409   g_return_val_if_fail (pspec_info->instance_size >= sizeof (GParamSpec), 0);
1410   g_return_val_if_fail (g_type_name (pspec_info->value_type) != NULL, 0);
1411   /* default: g_return_val_if_fail (pspec_info->value_set_default != NULL, 0); */
1412   /* optional: g_return_val_if_fail (pspec_info->value_validate != NULL, 0); */
1413   /* default: g_return_val_if_fail (pspec_info->values_cmp != NULL, 0); */
1414
1415   info.instance_size = pspec_info->instance_size;
1416   info.n_preallocs = pspec_info->n_preallocs;
1417   info.instance_init = (GInstanceInitFunc) pspec_info->instance_init;
1418   cinfo = g_new (ParamSpecClassInfo, 1);
1419   cinfo->value_type = pspec_info->value_type;
1420   cinfo->finalize = pspec_info->finalize;
1421   cinfo->value_set_default = pspec_info->value_set_default ? pspec_info->value_set_default : default_value_set_default;
1422   cinfo->value_validate = pspec_info->value_validate;
1423   cinfo->values_cmp = pspec_info->values_cmp ? pspec_info->values_cmp : default_values_cmp;
1424   info.class_data = cinfo;
1425
1426   return g_type_register_static (G_TYPE_PARAM, name, &info, 0);
1427 }
1428
1429 /**
1430  * g_value_set_param:
1431  * @value: a valid #GValue of type %G_TYPE_PARAM
1432  * @param: (allow-none): the #GParamSpec to be set
1433  *
1434  * Set the contents of a %G_TYPE_PARAM #GValue to @param.
1435  */
1436 void
1437 g_value_set_param (GValue     *value,
1438                    GParamSpec *param)
1439 {
1440   g_return_if_fail (G_VALUE_HOLDS_PARAM (value));
1441   if (param)
1442     g_return_if_fail (G_IS_PARAM_SPEC (param));
1443
1444   if (value->data[0].v_pointer)
1445     g_param_spec_unref (value->data[0].v_pointer);
1446   value->data[0].v_pointer = param;
1447   if (value->data[0].v_pointer)
1448     g_param_spec_ref (value->data[0].v_pointer);
1449 }
1450
1451 /**
1452  * g_value_set_param_take_ownership: (skip)
1453  * @value: a valid #GValue of type %G_TYPE_PARAM
1454  * @param: (allow-none): the #GParamSpec to be set
1455  *
1456  * This is an internal function introduced mainly for C marshallers.
1457  *
1458  * Deprecated: 2.4: Use g_value_take_param() instead.
1459  */
1460 void
1461 g_value_set_param_take_ownership (GValue     *value,
1462                                   GParamSpec *param)
1463 {
1464   g_value_take_param (value, param);
1465 }
1466
1467 /**
1468  * g_value_take_param: (skip)
1469  * @value: a valid #GValue of type %G_TYPE_PARAM
1470  * @param: (allow-none): the #GParamSpec to be set
1471  *
1472  * Sets the contents of a %G_TYPE_PARAM #GValue to @param and takes
1473  * over the ownership of the callers reference to @param; the caller
1474  * doesn't have to unref it any more.
1475  *
1476  * Since: 2.4
1477  */
1478 void
1479 g_value_take_param (GValue     *value,
1480                     GParamSpec *param)
1481 {
1482   g_return_if_fail (G_VALUE_HOLDS_PARAM (value));
1483   if (param)
1484     g_return_if_fail (G_IS_PARAM_SPEC (param));
1485
1486   if (value->data[0].v_pointer)
1487     g_param_spec_unref (value->data[0].v_pointer);
1488   value->data[0].v_pointer = param; /* we take over the reference count */
1489 }
1490
1491 /**
1492  * g_value_get_param:
1493  * @value: a valid #GValue whose type is derived from %G_TYPE_PARAM
1494  *
1495  * Get the contents of a %G_TYPE_PARAM #GValue.
1496  *
1497  * Returns: (transfer none): #GParamSpec content of @value
1498  */
1499 GParamSpec*
1500 g_value_get_param (const GValue *value)
1501 {
1502   g_return_val_if_fail (G_VALUE_HOLDS_PARAM (value), NULL);
1503
1504   return value->data[0].v_pointer;
1505 }
1506
1507 /**
1508  * g_value_dup_param: (skip)
1509  * @value: a valid #GValue whose type is derived from %G_TYPE_PARAM
1510  *
1511  * Get the contents of a %G_TYPE_PARAM #GValue, increasing its
1512  * reference count.
1513  *
1514  * Returns: #GParamSpec content of @value, should be unreferenced when
1515  *          no longer needed.
1516  */
1517 GParamSpec*
1518 g_value_dup_param (const GValue *value)
1519 {
1520   g_return_val_if_fail (G_VALUE_HOLDS_PARAM (value), NULL);
1521
1522   return value->data[0].v_pointer ? g_param_spec_ref (value->data[0].v_pointer) : NULL;
1523 }
1524
1525 /**
1526  * g_param_get_default_value:
1527  * @param: a #GParamSpec
1528  *
1529  * Gets the default value of @param as a pointer to a #GValue.
1530  *
1531  * The #GValue will remain value for the life of @param.
1532  *
1533  * Returns: a pointer to a #GValue which must not be modified
1534  *
1535  * Since: 2.38
1536  **/
1537 const GValue *
1538 g_param_spec_get_default_value (GParamSpec *pspec)
1539 {
1540   GParamSpecPrivate *priv = PRIV (pspec);
1541
1542   /* We use the type field of the GValue as the key for the once because
1543    * it will be zero before it is initialised and non-zero after.  We
1544    * have to take care that we don't write a non-zero value to the type
1545    * field before we are completely done, however, because then another
1546    * thread could come along and find the value partially-initialised.
1547    *
1548    * In order to accomplish this we store the default value in a
1549    * stack-allocated GValue.  We then set the type field in that value
1550    * to zero and copy the contents into place.  We then end by storing
1551    * the type as the last step in order to ensure that we're completely
1552    * done before a g_once_init_enter() could take the fast path in
1553    * another thread.
1554    */
1555   if (g_once_init_enter (&priv->default_value.g_type))
1556     {
1557       GValue default_value = G_VALUE_INIT;
1558
1559       g_value_init (&default_value, pspec->value_type);
1560       g_param_value_set_default (pspec, &default_value);
1561
1562       /* store all but the type */
1563       default_value.g_type = 0;
1564       priv->default_value = default_value;
1565
1566       g_once_init_leave (&priv->default_value.g_type, pspec->value_type);
1567     }
1568
1569   return &priv->default_value;
1570 }