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