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