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