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