LCOV - code coverage report
Current view: top level - gobject - gparam.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 82.7 % 513 424
Test Date: 2024-11-26 05:23:01 Functions: 82.3 % 62 51
Branches: - 0 0

             Branch data     Line data    Source code
       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                 :     3243387 : g_param_spec_get_private (GParamSpec *pspec)
      95                 :             : {
      96                 :     3243387 :   return &G_STRUCT_MEMBER (GParamSpecPrivate, pspec, g_param_private_offset);
      97                 :             : }
      98                 :             : 
      99                 :             : void
     100                 :         545 : _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                 :         545 :   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                 :         545 :   type = g_type_register_fundamental (G_TYPE_PARAM, g_intern_static_string ("GParam"), &param_spec_info, &finfo, G_TYPE_FLAG_ABSTRACT);
     141                 :         545 :   g_assert (type == G_TYPE_PARAM);
     142                 :         545 :   g_param_private_offset = g_type_add_instance_private (type, sizeof (GParamSpecPrivate));
     143                 :         545 :   g_value_register_transform_func (G_TYPE_PARAM, G_TYPE_PARAM, value_param_transform_value);
     144                 :         545 : }
     145                 :             : 
     146                 :             : static void
     147                 :       11665 : g_param_spec_class_base_init (GParamSpecClass *class)
     148                 :             : {
     149                 :       11665 : }
     150                 :             : 
     151                 :             : static void
     152                 :           0 : g_param_spec_class_base_finalize (GParamSpecClass *class)
     153                 :             : {
     154                 :           0 : }
     155                 :             : 
     156                 :             : static void
     157                 :         545 : g_param_spec_class_init (GParamSpecClass *class,
     158                 :             :                          gpointer         class_data)
     159                 :             : {
     160                 :         545 :   class->value_type = G_TYPE_NONE;
     161                 :         545 :   class->finalize = g_param_spec_finalize;
     162                 :         545 :   class->value_set_default = NULL;
     163                 :         545 :   class->value_validate = NULL;
     164                 :         545 :   class->values_cmp = NULL;
     165                 :             : 
     166                 :         545 :   g_type_class_adjust_private_offset (class, &g_param_private_offset);
     167                 :         545 : }
     168                 :             : 
     169                 :             : static void
     170                 :       10923 : g_param_spec_init (GParamSpec      *pspec,
     171                 :             :                    GParamSpecClass *class)
     172                 :             : {
     173                 :       10923 :   pspec->name = NULL;
     174                 :       10923 :   pspec->_nick = NULL;
     175                 :       10923 :   pspec->_blurb = NULL;
     176                 :       10923 :   pspec->flags = 0;
     177                 :       10923 :   pspec->value_type = class->value_type;
     178                 :       10923 :   pspec->owner_type = 0;
     179                 :       10923 :   pspec->qdata = NULL;
     180                 :       10923 :   g_datalist_set_flags (&pspec->qdata, PARAM_FLOATING_FLAG);
     181                 :       10923 :   pspec->ref_count = 1;
     182                 :       10923 :   pspec->param_id = 0;
     183                 :       10923 : }
     184                 :             : 
     185                 :             : static void
     186                 :          42 : g_param_spec_finalize (GParamSpec *pspec)
     187                 :             : {
     188                 :          42 :   GParamSpecPrivate *priv = g_param_spec_get_private (pspec);
     189                 :             : 
     190                 :          42 :   if (priv->default_value.g_type)
     191                 :           1 :     g_value_reset (&priv->default_value);
     192                 :             : 
     193                 :          42 :   g_datalist_clear (&pspec->qdata);
     194                 :             : 
     195                 :          42 :   if (!(pspec->flags & G_PARAM_STATIC_NICK))
     196                 :          42 :     g_free (pspec->_nick);
     197                 :             : 
     198                 :          42 :   if (!(pspec->flags & G_PARAM_STATIC_BLURB))
     199                 :          42 :     g_free (pspec->_blurb);
     200                 :             : 
     201                 :          42 :   g_type_free_instance ((GTypeInstance*) pspec);
     202                 :          42 : }
     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                 :     3070893 : g_param_spec_ref (GParamSpec *pspec)
     214                 :             : {
     215                 :     3070893 :   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
     216                 :             : 
     217                 :     3070893 :   g_atomic_int_inc ((int *)&pspec->ref_count);
     218                 :             : 
     219                 :     3070893 :   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                 :     3059408 : g_param_spec_unref (GParamSpec *pspec)
     230                 :             : {
     231                 :             :   gboolean is_zero;
     232                 :             : 
     233                 :     3059408 :   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
     234                 :             : 
     235                 :     3059408 :   is_zero = g_atomic_int_dec_and_test ((int *)&pspec->ref_count);
     236                 :             : 
     237                 :     3059408 :   if (G_UNLIKELY (is_zero))
     238                 :             :     {
     239                 :          42 :       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                 :           0 : g_param_spec_sink (GParamSpec *pspec)
     257                 :             : {
     258                 :             :   guintptr oldvalue;
     259                 :           0 :   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
     260                 :             : 
     261                 :           0 :   oldvalue = g_atomic_pointer_and (&pspec->qdata, ~(gsize)PARAM_FLOATING_FLAG);
     262                 :           0 :   if (oldvalue & PARAM_FLOATING_FLAG)
     263                 :           0 :     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                 :       10882 : g_param_spec_ref_sink (GParamSpec *pspec)
     277                 :             : {
     278                 :             :   guintptr oldvalue;
     279                 :       10882 :   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
     280                 :             : 
     281                 :       10882 :   oldvalue = g_atomic_pointer_and (&pspec->qdata, ~(gsize)PARAM_FLOATING_FLAG);
     282                 :       10882 :   if (!(oldvalue & PARAM_FLOATING_FLAG))
     283                 :           0 :     g_param_spec_ref (pspec);
     284                 :             : 
     285                 :       10882 :   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                 :          10 : g_param_spec_get_name (GParamSpec *pspec)
     301                 :             : {
     302                 :          10 :   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
     303                 :             : 
     304                 :          10 :   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                 :          32 : g_param_spec_get_nick (GParamSpec *pspec)
     317                 :             : {
     318                 :          32 :   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
     319                 :             : 
     320                 :          32 :   if (pspec->_nick)
     321                 :          28 :     return pspec->_nick;
     322                 :             :   else
     323                 :             :     {
     324                 :             :       GParamSpec *redirect_target;
     325                 :             : 
     326                 :           4 :       redirect_target = g_param_spec_get_redirect_target (pspec);
     327                 :           4 :       if (redirect_target && redirect_target->_nick)
     328                 :           3 :         return redirect_target->_nick;
     329                 :             :     }
     330                 :             : 
     331                 :           1 :   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                 :           6 : g_param_spec_get_blurb (GParamSpec *pspec)
     344                 :             : {
     345                 :           6 :   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
     346                 :             : 
     347                 :           6 :   if (pspec->_blurb)
     348                 :           2 :     return pspec->_blurb;
     349                 :             :   else
     350                 :             :     {
     351                 :             :       GParamSpec *redirect_target;
     352                 :             : 
     353                 :           4 :       redirect_target = g_param_spec_get_redirect_target (pspec);
     354                 :           4 :       if (redirect_target && redirect_target->_blurb)
     355                 :           3 :         return redirect_target->_blurb;
     356                 :             :     }
     357                 :             : 
     358                 :           1 :   return NULL;
     359                 :             : }
     360                 :             : 
     361                 :             : /* @key must have already been validated with is_valid()
     362                 :             :  * Modifies @key in place. */
     363                 :             : static void
     364                 :          62 : canonicalize_key (gchar *key)
     365                 :             : {
     366                 :             :   gchar *p;
     367                 :             :   
     368                 :         561 :   for (p = key; *p != 0; p++)
     369                 :             :     {
     370                 :         499 :       gchar c = *p;
     371                 :             :       
     372                 :         499 :       if (c == '_')
     373                 :          62 :         *p = '-';
     374                 :             :     }
     375                 :          62 : }
     376                 :             : 
     377                 :             : /* @key must have already been validated with is_valid() */
     378                 :             : static gboolean
     379                 :       43437 : is_canonical (const gchar *key)
     380                 :             : {
     381                 :       43437 :   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][class@GObject.ParamSpec#parameter-names]
     393                 :             :  * for details of 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                 :       13097 : g_param_spec_is_valid_name (const gchar *name)
     400                 :             : {
     401                 :             :   const gchar *p;
     402                 :             : 
     403                 :             :   /* First character must be a letter. */
     404                 :       13097 :   if ((name[0] < 'A' || name[0] > 'Z') &&
     405                 :       13097 :       (name[0] < 'a' || name[0] > 'z'))
     406                 :           4 :     return FALSE;
     407                 :             : 
     408                 :      143782 :   for (p = name; *p != 0; p++)
     409                 :             :     {
     410                 :      130691 :       const gchar c = *p;
     411                 :             : 
     412                 :      130691 :       if (c != '-' && c != '_' &&
     413                 :      121756 :           (c < '0' || c > '9') &&
     414                 :      121597 :           (c < 'A' || c > 'Z') &&
     415                 :      121581 :           (c < 'a' || c > 'z'))
     416                 :           2 :         return FALSE;
     417                 :             :     }
     418                 :             : 
     419                 :       13091 :   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][class@GObject.ParamSpec#parameter-names]
     433                 :             :  * for details of the rules for @name. Names which violate these rules lead
     434                 :             :  * to undefined 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                 :       10923 : 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                 :       10923 :   g_return_val_if_fail (G_TYPE_IS_PARAM (param_type) && param_type != G_TYPE_PARAM, NULL);
     457                 :       10923 :   g_return_val_if_fail (name != NULL, NULL);
     458                 :       10923 :   g_return_val_if_fail (g_param_spec_is_valid_name (name), NULL);
     459                 :       10923 :   g_return_val_if_fail (!(flags & G_PARAM_STATIC_NAME) || is_canonical (name), NULL);
     460                 :             :   
     461                 :       10923 :   pspec = (gpointer) g_type_create_instance (param_type);
     462                 :             : 
     463                 :       10923 :   if (flags & G_PARAM_STATIC_NAME)
     464                 :             :     {
     465                 :             :       /* pspec->name is not freed if (flags & G_PARAM_STATIC_NAME) */
     466                 :       10746 :       pspec->name = (gchar *) g_intern_static_string (name);
     467                 :       10746 :       if (!is_canonical (pspec->name))
     468                 :           0 :         g_warning ("G_PARAM_STATIC_NAME used with non-canonical pspec name: %s", pspec->name);
     469                 :             :     }
     470                 :             :   else
     471                 :             :     {
     472                 :         177 :       if (is_canonical (name))
     473                 :         176 :         pspec->name = (gchar *) g_intern_string (name);
     474                 :             :       else
     475                 :             :         {
     476                 :           1 :           gchar *tmp = g_strdup (name);
     477                 :           1 :           canonicalize_key (tmp);
     478                 :           1 :           pspec->name = (gchar *) g_intern_string (tmp);
     479                 :           1 :           g_free (tmp);
     480                 :             :         }
     481                 :             :     }
     482                 :             : 
     483                 :       10923 :   priv = g_param_spec_get_private (pspec);
     484                 :       10923 :   priv->name_quark = g_quark_from_string (pspec->name);
     485                 :             : 
     486                 :       10923 :   if (flags & G_PARAM_STATIC_NICK)
     487                 :       10437 :     pspec->_nick = (gchar*) nick;
     488                 :             :   else
     489                 :         486 :     pspec->_nick = g_strdup (nick);
     490                 :             : 
     491                 :       10923 :   if (flags & G_PARAM_STATIC_BLURB)
     492                 :       10746 :     pspec->_blurb = (gchar*) blurb;
     493                 :             :   else
     494                 :         177 :     pspec->_blurb = g_strdup (blurb);
     495                 :             : 
     496                 :       10923 :   pspec->flags = (flags & G_PARAM_USER_MASK) | (flags & G_PARAM_MASK);
     497                 :             :   
     498                 :       10923 :   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                 :           2 : g_param_spec_get_qdata (GParamSpec *pspec,
     512                 :             :                         GQuark      quark)
     513                 :             : {
     514                 :           2 :   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
     515                 :             :   
     516                 :           2 :   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                 :           1 : g_param_spec_set_qdata (GParamSpec *pspec,
     534                 :             :                         GQuark      quark,
     535                 :             :                         gpointer    data)
     536                 :             : {
     537                 :           1 :   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
     538                 :           1 :   g_return_if_fail (quark > 0);
     539                 :             : 
     540                 :           1 :   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                 :           2 : g_param_spec_set_qdata_full (GParamSpec    *pspec,
     559                 :             :                              GQuark         quark,
     560                 :             :                              gpointer       data,
     561                 :             :                              GDestroyNotify destroy)
     562                 :             : {
     563                 :           2 :   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
     564                 :           2 :   g_return_if_fail (quark > 0);
     565                 :             : 
     566                 :           2 :   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                 :           1 : g_param_spec_steal_qdata (GParamSpec *pspec,
     583                 :             :                           GQuark      quark)
     584                 :             : {
     585                 :           1 :   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
     586                 :           1 :   g_return_val_if_fail (quark > 0, NULL);
     587                 :             :   
     588                 :           1 :   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                 :        1962 : g_param_spec_get_redirect_target (GParamSpec *pspec)
     610                 :             : {
     611                 :        1962 :   GTypeInstance *inst = (GTypeInstance *)pspec;
     612                 :             : 
     613                 :        1962 :   if (inst && inst->g_class && inst->g_class->g_type == G_TYPE_PARAM_OVERRIDE)
     614                 :         144 :     return ((GParamSpecOverride*)pspec)->overridden;
     615                 :             :   else
     616                 :        1818 :     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                 :        2906 : g_param_value_set_default (GParamSpec *pspec,
     629                 :             :                            GValue     *value)
     630                 :             : {
     631                 :        2906 :   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
     632                 :             : 
     633                 :        2906 :   if (G_VALUE_TYPE (value) == G_TYPE_INVALID)
     634                 :             :     {
     635                 :           8 :       g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
     636                 :             :     }
     637                 :             :   else
     638                 :             :     {
     639                 :        2898 :       g_return_if_fail (G_IS_VALUE (value));
     640                 :        2898 :       g_return_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value));
     641                 :        2898 :       g_value_reset (value);
     642                 :             :     }
     643                 :             : 
     644                 :        2906 :   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                 :          91 : g_param_value_defaults (GParamSpec   *pspec,
     658                 :             :                         const GValue *value)
     659                 :             : {
     660                 :          91 :   GValue dflt_value = G_VALUE_INIT;
     661                 :             :   gboolean defaults;
     662                 :             : 
     663                 :          91 :   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
     664                 :          91 :   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
     665                 :          91 :   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE);
     666                 :             : 
     667                 :          91 :   g_value_init (&dflt_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
     668                 :          91 :   G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, &dflt_value);
     669                 :          91 :   defaults = G_PARAM_SPEC_GET_CLASS (pspec)->values_cmp (pspec, value, &dflt_value) == 0;
     670                 :          91 :   g_value_unset (&dflt_value);
     671                 :             : 
     672                 :          91 :   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                 :        8493 : g_param_value_validate (GParamSpec *pspec,
     691                 :             :                         GValue     *value)
     692                 :             : {
     693                 :        8493 :   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
     694                 :        8493 :   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
     695                 :        8493 :   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE);
     696                 :             : 
     697                 :        8493 :   if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate)
     698                 :             :     {
     699                 :        8493 :       GValue oval = *value;
     700                 :             : 
     701                 :        8493 :       if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate (pspec, value) ||
     702                 :        8459 :           memcmp (&oval.data, &value->data, sizeof (oval.data)))
     703                 :          34 :         return TRUE;
     704                 :             :     }
     705                 :             : 
     706                 :        8459 :   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                 :          46 : g_param_value_is_valid (GParamSpec *pspec,
     724                 :             :                         const GValue *value)
     725                 :             : {
     726                 :             :   GParamSpecClass *class;
     727                 :             : 
     728                 :          46 :   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), TRUE);
     729                 :          46 :   g_return_val_if_fail (G_IS_VALUE (value), TRUE);
     730                 :          46 :   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), TRUE);
     731                 :             : 
     732                 :          46 :   class = G_PARAM_SPEC_GET_CLASS (pspec);
     733                 :             : 
     734                 :          46 :   if (class->value_is_valid)
     735                 :          45 :     return class->value_is_valid (pspec, value);
     736                 :           1 :   else if (class->value_validate)
     737                 :             :     {
     738                 :           1 :       GValue val = G_VALUE_INIT;
     739                 :             :       gboolean changed;
     740                 :             : 
     741                 :           1 :       g_value_init (&val, G_VALUE_TYPE (value));
     742                 :           1 :       g_value_copy (value, &val);
     743                 :             : 
     744                 :           1 :       changed = class->value_validate (pspec, &val);
     745                 :             : 
     746                 :           1 :       g_value_unset (&val);
     747                 :             : 
     748                 :           1 :       return !changed;
     749                 :             :     }
     750                 :             : 
     751                 :           0 :   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                 :           2 : g_param_value_convert (GParamSpec   *pspec,
     775                 :             :                        const GValue *src_value,
     776                 :             :                        GValue       *dest_value,
     777                 :             :                        gboolean      strict_validation)
     778                 :             : {
     779                 :           2 :   GValue tmp_value = G_VALUE_INIT;
     780                 :             : 
     781                 :           2 :   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
     782                 :           2 :   g_return_val_if_fail (G_IS_VALUE (src_value), FALSE);
     783                 :           2 :   g_return_val_if_fail (G_IS_VALUE (dest_value), FALSE);
     784                 :           2 :   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                 :           2 :   g_value_init (&tmp_value, G_VALUE_TYPE (dest_value));
     789                 :           4 :   if (g_value_transform (src_value, &tmp_value) &&
     790                 :           4 :       (!g_param_value_validate (pspec, &tmp_value) || !strict_validation))
     791                 :             :     {
     792                 :           1 :       g_value_unset (dest_value);
     793                 :             :       
     794                 :             :       /* values are relocatable */
     795                 :           1 :       memcpy (dest_value, &tmp_value, sizeof (tmp_value));
     796                 :             :       
     797                 :           1 :       return TRUE;
     798                 :             :     }
     799                 :             :   else
     800                 :             :     {
     801                 :           1 :       g_value_unset (&tmp_value);
     802                 :             :       
     803                 :           1 :       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                 :          19 : 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                 :          19 :   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), 0);
     833                 :          19 :   g_return_val_if_fail (G_IS_VALUE (value1), 0);
     834                 :          19 :   g_return_val_if_fail (G_IS_VALUE (value2), 0);
     835                 :          19 :   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value1), 0);
     836                 :          19 :   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value2), 0);
     837                 :             : 
     838                 :          19 :   cmp = G_PARAM_SPEC_GET_CLASS (pspec)->values_cmp (pspec, value1, value2);
     839                 :             : 
     840                 :          19 :   return CLAMP (cmp, -1, 1);
     841                 :             : }
     842                 :             : 
     843                 :             : static void
     844                 :           4 : value_param_init (GValue *value)
     845                 :             : {
     846                 :           4 :   value->data[0].v_pointer = NULL;
     847                 :           4 : }
     848                 :             : 
     849                 :             : static void
     850                 :     3059360 : value_param_free_value (GValue *value)
     851                 :             : {
     852                 :     3059360 :   if (value->data[0].v_pointer)
     853                 :     3059359 :     g_param_spec_unref (value->data[0].v_pointer);
     854                 :     3059360 : }
     855                 :             : 
     856                 :             : static void
     857                 :           0 : value_param_copy_value (const GValue *src_value,
     858                 :             :                         GValue       *dest_value)
     859                 :             : {
     860                 :           0 :   if (src_value->data[0].v_pointer)
     861                 :           0 :     dest_value->data[0].v_pointer = g_param_spec_ref (src_value->data[0].v_pointer);
     862                 :             :   else
     863                 :           0 :     dest_value->data[0].v_pointer = NULL;
     864                 :           0 : }
     865                 :             : 
     866                 :             : static void
     867                 :           0 : value_param_transform_value (const GValue *src_value,
     868                 :             :                              GValue       *dest_value)
     869                 :             : {
     870                 :           0 :   if (src_value->data[0].v_pointer &&
     871                 :           0 :       g_type_is_a (G_PARAM_SPEC_TYPE (dest_value->data[0].v_pointer), G_VALUE_TYPE (dest_value)))
     872                 :           0 :     dest_value->data[0].v_pointer = g_param_spec_ref (src_value->data[0].v_pointer);
     873                 :             :   else
     874                 :           0 :     dest_value->data[0].v_pointer = NULL;
     875                 :           0 : }
     876                 :             : 
     877                 :             : static gpointer
     878                 :           0 : value_param_peek_pointer (const GValue *value)
     879                 :             : {
     880                 :           0 :   return value->data[0].v_pointer;
     881                 :             : }
     882                 :             : 
     883                 :             : static gchar*
     884                 :     3059356 : value_param_collect_value (GValue      *value,
     885                 :             :                            guint        n_collect_values,
     886                 :             :                            GTypeCValue *collect_values,
     887                 :             :                            guint        collect_flags)
     888                 :             : {
     889                 :     3059356 :   if (collect_values[0].v_pointer)
     890                 :             :     {
     891                 :     3059356 :       GParamSpec *param = collect_values[0].v_pointer;
     892                 :             : 
     893                 :     3059356 :       if (param->g_type_instance.g_class == NULL)
     894                 :           0 :         return g_strconcat ("invalid unclassed param spec pointer for value type '",
     895                 :             :                             G_VALUE_TYPE_NAME (value),
     896                 :             :                             "'",
     897                 :             :                             NULL);
     898                 :     3059356 :       else if (!g_value_type_compatible (G_PARAM_SPEC_TYPE (param), G_VALUE_TYPE (value)))
     899                 :           0 :         return g_strconcat ("invalid param spec type '",
     900                 :           0 :                             G_PARAM_SPEC_TYPE_NAME (param),
     901                 :             :                             "' for value type '",
     902                 :             :                             G_VALUE_TYPE_NAME (value),
     903                 :             :                             "'",
     904                 :             :                             NULL);
     905                 :     3059356 :       value->data[0].v_pointer = g_param_spec_ref (param);
     906                 :             :     }
     907                 :             :   else
     908                 :           0 :     value->data[0].v_pointer = NULL;
     909                 :             : 
     910                 :     3059356 :   return NULL;
     911                 :             : }
     912                 :             : 
     913                 :             : static gchar*
     914                 :           0 : value_param_lcopy_value (const GValue *value,
     915                 :             :                          guint         n_collect_values,
     916                 :             :                          GTypeCValue  *collect_values,
     917                 :             :                          guint         collect_flags)
     918                 :             : {
     919                 :           0 :   GParamSpec **param_p = collect_values[0].v_pointer;
     920                 :             : 
     921                 :           0 :   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                 :           0 :   if (!value->data[0].v_pointer)
     924                 :           0 :     *param_p = NULL;
     925                 :           0 :   else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
     926                 :           0 :     *param_p = value->data[0].v_pointer;
     927                 :             :   else
     928                 :           0 :     *param_p = g_param_spec_ref (value->data[0].v_pointer);
     929                 :             : 
     930                 :           0 :   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                 :    24105530 : param_spec_pool_hash (gconstpointer key_spec)
     953                 :             : {
     954                 :    24105530 :   const GParamSpec *key = key_spec;
     955                 :             :   const gchar *p;
     956                 :    24105530 :   guint h = (guint) key->owner_type;
     957                 :             : 
     958                 :   158201703 :   for (p = key->name; *p; p++)
     959                 :   134096173 :     h = (h << 5) - h + *p;
     960                 :             : 
     961                 :    24105530 :   return h;
     962                 :             : }
     963                 :             : 
     964                 :             : static gboolean
     965                 :    24038155 : param_spec_pool_equals (gconstpointer key_spec_1,
     966                 :             :                         gconstpointer key_spec_2)
     967                 :             : {
     968                 :    24038155 :   const GParamSpec *key1 = key_spec_1;
     969                 :    24038155 :   const GParamSpec *key2 = key_spec_2;
     970                 :             : 
     971                 :    48076310 :   return (key1->owner_type == key2->owner_type &&
     972                 :    24038155 :           (key1->name == key2->name ||
     973                 :    23679470 :            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                 :         340 : g_param_spec_pool_new (gboolean type_prefixing)
     991                 :             : {
     992                 :             :   static GMutex init_mutex;
     993                 :         340 :   GParamSpecPool *pool = g_new (GParamSpecPool, 1);
     994                 :             : 
     995                 :         340 :   memcpy (&pool->mutex, &init_mutex, sizeof (init_mutex));
     996                 :         340 :   pool->type_prefixing = type_prefixing != FALSE;
     997                 :         340 :   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                 :         340 :   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                 :           1 : g_param_spec_pool_free (GParamSpecPool *pool)
    1015                 :             : {
    1016                 :           1 :   g_mutex_lock (&pool->mutex);
    1017                 :           1 :   g_hash_table_unref (pool->hash_table);
    1018                 :           1 :   g_mutex_unlock (&pool->mutex);
    1019                 :           1 :   g_mutex_clear (&pool->mutex);
    1020                 :           1 :   g_free (pool);
    1021                 :           1 : }
    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                 :       10881 : g_param_spec_pool_insert (GParamSpecPool *pool,
    1033                 :             :                           GParamSpec     *pspec,
    1034                 :             :                           GType           owner_type)
    1035                 :             : {
    1036                 :             :   const gchar *p;
    1037                 :             :   
    1038                 :       10881 :   if (pool && pspec && owner_type > 0 && pspec->owner_type == 0)
    1039                 :             :     {
    1040                 :      118227 :       for (p = pspec->name; *p; p++)
    1041                 :             :         {
    1042                 :      107346 :           if (!strchr (G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-_", *p))
    1043                 :             :             {
    1044                 :           0 :               g_critical (G_STRLOC ": pspec name \"%s\" contains invalid characters", pspec->name);
    1045                 :           0 :               return;
    1046                 :             :             }
    1047                 :             :         }
    1048                 :       10881 :       g_mutex_lock (&pool->mutex);
    1049                 :       10881 :       pspec->owner_type = owner_type;
    1050                 :       10881 :       g_param_spec_ref (pspec);
    1051                 :       10881 :       g_hash_table_add (pool->hash_table, pspec);
    1052                 :       10881 :       g_mutex_unlock (&pool->mutex);
    1053                 :             :     }
    1054                 :             :   else
    1055                 :             :     {
    1056                 :           0 :       g_return_if_fail (pool != NULL);
    1057                 :           0 :       g_return_if_fail (pspec);
    1058                 :           0 :       g_return_if_fail (owner_type > 0);
    1059                 :           0 :       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                 :           1 : g_param_spec_pool_remove (GParamSpecPool *pool,
    1072                 :             :                           GParamSpec     *pspec)
    1073                 :             : {
    1074                 :           1 :   if (pool && pspec)
    1075                 :             :     {
    1076                 :           1 :       g_mutex_lock (&pool->mutex);
    1077                 :           1 :       if (!g_hash_table_remove (pool->hash_table, pspec))
    1078                 :           0 :         g_critical (G_STRLOC ": attempt to remove unknown pspec '%s' from pool", pspec->name);
    1079                 :           1 :       g_mutex_unlock (&pool->mutex);
    1080                 :             :     }
    1081                 :             :   else
    1082                 :             :     {
    1083                 :           0 :       g_return_if_fail (pool != NULL);
    1084                 :           0 :       g_return_if_fail (pspec);
    1085                 :             :     }
    1086                 :             : }
    1087                 :             : 
    1088                 :             : static inline GParamSpec*
    1089                 :    24059861 : 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                 :    24059861 :   key.owner_type = owner_type;
    1097                 :    24059861 :   key.name = (gchar*) param_name;
    1098                 :    24059861 :   if (walk_ancestors)
    1099                 :             :     do
    1100                 :             :       {
    1101                 :    24083210 :         pspec = g_hash_table_lookup (hash_table, &key);
    1102                 :    24083210 :         if (pspec)
    1103                 :    24037643 :           return pspec;
    1104                 :       45567 :         key.owner_type = g_type_parent (key.owner_type);
    1105                 :             :       }
    1106                 :       45567 :     while (key.owner_type);
    1107                 :             :   else
    1108                 :       11377 :     pspec = g_hash_table_lookup (hash_table, &key);
    1109                 :             : 
    1110                 :       22218 :   if (!pspec && !is_canonical (param_name))
    1111                 :             :     {
    1112                 :             :       gchar *canonical;
    1113                 :             : 
    1114                 :          61 :       canonical = g_strdup (key.name);
    1115                 :          61 :       canonicalize_key (canonical);
    1116                 :             : 
    1117                 :             :       /* try canonicalized form */
    1118                 :          61 :       key.name = canonical;
    1119                 :          61 :       key.owner_type = owner_type;
    1120                 :             : 
    1121                 :          61 :       if (walk_ancestors)
    1122                 :             :         do
    1123                 :             :           {
    1124                 :          61 :             pspec = g_hash_table_lookup (hash_table, &key);
    1125                 :          61 :             if (pspec)
    1126                 :             :               {
    1127                 :          61 :                 g_free (canonical);
    1128                 :          61 :                 return pspec;
    1129                 :             :               }
    1130                 :           0 :             key.owner_type = g_type_parent (key.owner_type);
    1131                 :             :           }
    1132                 :           0 :         while (key.owner_type);
    1133                 :             :       else
    1134                 :           0 :         pspec = g_hash_table_lookup (hash_table, &key);
    1135                 :             : 
    1136                 :           0 :       g_free (canonical);
    1137                 :             :     }
    1138                 :             : 
    1139                 :       22157 :   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                 :    24058711 : 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                 :    24058711 :   g_return_val_if_fail (pool != NULL, NULL);
    1164                 :    24058711 :   g_return_val_if_fail (param_name != NULL, NULL);
    1165                 :             : 
    1166                 :    24058711 :   g_mutex_lock (&pool->mutex);
    1167                 :             : 
    1168                 :             :   /* try quick and away, i.e. without prefix */
    1169                 :    24058711 :   pspec = param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
    1170                 :    24058711 :   if (pspec)
    1171                 :             :     {
    1172                 :    24037004 :       g_mutex_unlock (&pool->mutex);
    1173                 :    24037004 :       return pspec;
    1174                 :             :     }
    1175                 :             : 
    1176                 :       21707 :   if (pool->type_prefixing)
    1177                 :             :     {
    1178                 :             :       char *delim;
    1179                 :             : 
    1180                 :       21706 :       delim = strchr (param_name, ':');
    1181                 :             : 
    1182                 :             :       /* strip type prefix */
    1183                 :       21706 :       if (delim && delim[1] == ':')
    1184                 :             :         {
    1185                 :           0 :           guint l = delim - param_name;
    1186                 :           0 :           gchar stack_buffer[32], *buffer = l < 32 ? stack_buffer : g_new (gchar, l + 1);
    1187                 :             :           GType type;
    1188                 :             : 
    1189                 :           0 :           strncpy (buffer, param_name, delim - param_name);
    1190                 :           0 :           buffer[l] = 0;
    1191                 :           0 :           type = g_type_from_name (buffer);
    1192                 :           0 :           if (l >= 32)
    1193                 :           0 :             g_free (buffer);
    1194                 :           0 :           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                 :           0 :               if ((!walk_ancestors && type != owner_type) || !g_type_is_a (owner_type, type))
    1198                 :             :                 {
    1199                 :           0 :                   g_mutex_unlock (&pool->mutex);
    1200                 :             : 
    1201                 :           0 :                   return NULL;
    1202                 :             :                 }
    1203                 :           0 :               owner_type = type;
    1204                 :           0 :               param_name += l + 2;
    1205                 :           0 :               pspec = param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
    1206                 :           0 :               g_mutex_unlock (&pool->mutex);
    1207                 :             : 
    1208                 :           0 :               return pspec;
    1209                 :             :             }
    1210                 :             :         }
    1211                 :             :     }
    1212                 :             : 
    1213                 :             :   /* malformed param_name */
    1214                 :             : 
    1215                 :       21707 :   g_mutex_unlock (&pool->mutex);
    1216                 :             : 
    1217                 :       21707 :   return NULL;
    1218                 :             : }
    1219                 :             : 
    1220                 :             : static void
    1221                 :           0 : pool_list (gpointer key,
    1222                 :             :            gpointer value,
    1223                 :             :            gpointer user_data)
    1224                 :             : {
    1225                 :           0 :   GParamSpec *pspec = value;
    1226                 :           0 :   gpointer *data = user_data;
    1227                 :           0 :   GType owner_type = (GType) data[1];
    1228                 :             : 
    1229                 :           0 :   if (owner_type == pspec->owner_type)
    1230                 :           0 :     data[0] = g_list_prepend (data[0], pspec);
    1231                 :           0 : }
    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                 :           0 : g_param_spec_pool_list_owned (GParamSpecPool *pool,
    1247                 :             :                               GType           owner_type)
    1248                 :             : {
    1249                 :             :   gpointer data[2];
    1250                 :             : 
    1251                 :           0 :   g_return_val_if_fail (pool != NULL, NULL);
    1252                 :           0 :   g_return_val_if_fail (owner_type > 0, NULL);
    1253                 :             :   
    1254                 :           0 :   g_mutex_lock (&pool->mutex);
    1255                 :           0 :   data[0] = NULL;
    1256                 :           0 :   data[1] = GTYPE_TO_POINTER (owner_type);
    1257                 :           0 :   g_hash_table_foreach (pool->hash_table, pool_list, &data);
    1258                 :           0 :   g_mutex_unlock (&pool->mutex);
    1259                 :             : 
    1260                 :           0 :   return data[0];
    1261                 :             : }
    1262                 :             : 
    1263                 :             : static gint
    1264                 :        2035 : pspec_compare_id (gconstpointer a,
    1265                 :             :                   gconstpointer b)
    1266                 :             : {
    1267                 :        2035 :   const GParamSpec *pspec1 = a, *pspec2 = b;
    1268                 :             : 
    1269                 :        2035 :   if (pspec1->param_id < pspec2->param_id)
    1270                 :         237 :     return -1;
    1271                 :             : 
    1272                 :        1798 :   if (pspec1->param_id > pspec2->param_id)
    1273                 :         309 :     return 1;
    1274                 :             : 
    1275                 :        1489 :   return strcmp (pspec1->name, pspec2->name);
    1276                 :             : }
    1277                 :             : 
    1278                 :             : static inline gboolean
    1279                 :        1155 : 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                 :        1155 :   if (g_param_spec_get_redirect_target (pspec))
    1291                 :           5 :     return FALSE;
    1292                 :             : 
    1293                 :        1150 :   found = param_spec_ht_lookup (ht, pspec->name, owner_type, TRUE);
    1294                 :        1150 :   if (found != pspec)
    1295                 :             :     {
    1296                 :          22 :       GParamSpec *redirect = g_param_spec_get_redirect_target (found);
    1297                 :          22 :       if (redirect != pspec)
    1298                 :          18 :         return FALSE;
    1299                 :             :     }
    1300                 :             : 
    1301                 :        1132 :   return TRUE;
    1302                 :             : }
    1303                 :             : 
    1304                 :             : static void
    1305                 :       17092 : pool_depth_list (gpointer key,
    1306                 :             :                  gpointer value,
    1307                 :             :                  gpointer user_data)
    1308                 :             : {
    1309                 :       17092 :   GParamSpec *pspec = value;
    1310                 :       17092 :   gpointer *data = user_data;
    1311                 :       17092 :   GSList **slists = data[0];
    1312                 :       17092 :   GType owner_type = (GType) data[1];
    1313                 :       17092 :   GHashTable *ht = data[2];
    1314                 :       17092 :   int *count = data[3];
    1315                 :             : 
    1316                 :       17519 :   if (g_type_is_a (owner_type, pspec->owner_type) &&
    1317                 :         427 :       should_list_pspec (pspec, owner_type, ht))
    1318                 :             :     {
    1319                 :         404 :       if (G_TYPE_IS_INTERFACE (pspec->owner_type))
    1320                 :             :         {
    1321                 :           3 :           slists[0] = g_slist_prepend (slists[0], pspec);
    1322                 :           3 :           *count = *count + 1;
    1323                 :             :         }
    1324                 :             :       else
    1325                 :             :         {
    1326                 :         401 :           guint d = g_type_depth (pspec->owner_type);
    1327                 :             : 
    1328                 :         401 :           slists[d - 1] = g_slist_prepend (slists[d - 1], pspec);
    1329                 :         401 :           *count = *count + 1;
    1330                 :             :         }
    1331                 :             :     }
    1332                 :       17092 : }
    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                 :             :  * prerequisites.
    1342                 :             :  */
    1343                 :             : static void
    1344                 :      109923 : pool_depth_list_for_interface (gpointer key,
    1345                 :             :                                gpointer value,
    1346                 :             :                                gpointer user_data)
    1347                 :             : {
    1348                 :      109923 :   GParamSpec *pspec = value;
    1349                 :      109923 :   gpointer *data = user_data;
    1350                 :      109923 :   GSList **slists = data[0];
    1351                 :      109923 :   GType owner_type = (GType) data[1];
    1352                 :      109923 :   GHashTable *ht = data[2];
    1353                 :      109923 :   int *count = data[3];
    1354                 :             : 
    1355                 :      110651 :   if (pspec->owner_type == owner_type &&
    1356                 :         728 :       should_list_pspec (pspec, owner_type, ht))
    1357                 :             :     {
    1358                 :         728 :       slists[0] = g_slist_prepend (slists[0], pspec);
    1359                 :         728 :       *count = *count + 1;
    1360                 :             :     }
    1361                 :      109923 : }
    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                 :        3198 : 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                 :        3198 :   int n_pspecs = 0;
    1386                 :             : 
    1387                 :        3198 :   g_return_val_if_fail (pool != NULL, NULL);
    1388                 :        3198 :   g_return_val_if_fail (owner_type > 0, NULL);
    1389                 :        3198 :   g_return_val_if_fail (n_pspecs_p != NULL, NULL);
    1390                 :             :   
    1391                 :        3198 :   g_mutex_lock (&pool->mutex);
    1392                 :        3198 :   d = g_type_depth (owner_type);
    1393                 :        3198 :   slists = g_new0 (GSList*, d);
    1394                 :        3198 :   data[0] = slists;
    1395                 :        3198 :   data[1] = GTYPE_TO_POINTER (owner_type);
    1396                 :        3198 :   data[2] = pool->hash_table;
    1397                 :        3198 :   data[3] = &n_pspecs;
    1398                 :             : 
    1399                 :        3198 :   g_hash_table_foreach (pool->hash_table,
    1400                 :        3198 :                         G_TYPE_IS_INTERFACE (owner_type) ?
    1401                 :             :                           pool_depth_list_for_interface :
    1402                 :             :                           pool_depth_list,
    1403                 :             :                         &data);
    1404                 :             : 
    1405                 :        3198 :   pspecs = g_new (GParamSpec*, n_pspecs + 1);
    1406                 :        3198 :   p = pspecs;
    1407                 :        9657 :   for (i = 0; i < d; i++)
    1408                 :             :     {
    1409                 :        6459 :       slists[i] = g_slist_sort (slists[i], pspec_compare_id);
    1410                 :        7591 :       for (node = slists[i]; node; node = node->next)
    1411                 :        1132 :         *p++ = node->data;
    1412                 :        6459 :       g_slist_free (slists[i]);
    1413                 :             :     }
    1414                 :        3198 :   *p++ = NULL;
    1415                 :        3198 :   g_free (slists);
    1416                 :        3198 :   g_mutex_unlock (&pool->mutex);
    1417                 :             : 
    1418                 :        3198 :   *n_pspecs_p = n_pspecs;
    1419                 :             : 
    1420                 :        3198 :   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                 :       11120 : param_spec_generic_class_init (gpointer g_class,
    1440                 :             :                                gpointer class_data)
    1441                 :             : {
    1442                 :       11120 :   GParamSpecClass *class = g_class;
    1443                 :       11120 :   ParamSpecClassInfo *info = class_data;
    1444                 :             : 
    1445                 :       11120 :   class->value_type = info->value_type;
    1446                 :       11120 :   if (info->finalize)
    1447                 :        2725 :     class->finalize = info->finalize;                     /* optional */
    1448                 :       11120 :   class->value_set_default = info->value_set_default;
    1449                 :       11120 :   if (info->value_validate)
    1450                 :       10901 :     class->value_validate = info->value_validate; /* optional */
    1451                 :       11120 :   class->values_cmp = info->values_cmp;
    1452                 :       11120 :   g_free (class_data);
    1453                 :       11120 : }
    1454                 :             : 
    1455                 :             : static void
    1456                 :           0 : default_value_set_default (GParamSpec *pspec,
    1457                 :             :                            GValue     *value)
    1458                 :             : {
    1459                 :             :   /* value is already zero initialized */
    1460                 :           0 : }
    1461                 :             : 
    1462                 :             : static gint
    1463                 :           0 : default_values_cmp (GParamSpec   *pspec,
    1464                 :             :                     const GValue *value1,
    1465                 :             :                     const GValue *value2)
    1466                 :             : {
    1467                 :           0 :   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                 :       12536 : g_param_type_register_static (const gchar              *name,
    1486                 :             :                               const GParamSpecTypeInfo *pspec_info)
    1487                 :             : {
    1488                 :       12536 :   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                 :       12536 :   g_return_val_if_fail (name != NULL, 0);
    1503                 :       12536 :   g_return_val_if_fail (pspec_info != NULL, 0);
    1504                 :       12536 :   g_return_val_if_fail (g_type_from_name (name) == 0, 0);
    1505                 :       12536 :   g_return_val_if_fail (pspec_info->instance_size >= sizeof (GParamSpec), 0);
    1506                 :       12536 :   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                 :       12536 :   info.instance_size = pspec_info->instance_size;
    1512                 :       12536 :   info.n_preallocs = pspec_info->n_preallocs;
    1513                 :       12536 :   info.instance_init = (GInstanceInitFunc) pspec_info->instance_init;
    1514                 :       12536 :   cinfo = g_new (ParamSpecClassInfo, 1);
    1515                 :       12536 :   cinfo->value_type = pspec_info->value_type;
    1516                 :       12536 :   cinfo->finalize = pspec_info->finalize;
    1517                 :       12536 :   cinfo->value_set_default = pspec_info->value_set_default ? pspec_info->value_set_default : default_value_set_default;
    1518                 :       12536 :   cinfo->value_validate = pspec_info->value_validate;
    1519                 :       12536 :   cinfo->values_cmp = pspec_info->values_cmp ? pspec_info->values_cmp : default_values_cmp;
    1520                 :       12536 :   info.class_data = cinfo;
    1521                 :             : 
    1522                 :       12536 :   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                 :           2 : g_value_set_param (GValue     *value,
    1534                 :             :                    GParamSpec *param)
    1535                 :             : {
    1536                 :           2 :   g_return_if_fail (G_VALUE_HOLDS_PARAM (value));
    1537                 :           2 :   if (param)
    1538                 :           2 :     g_return_if_fail (G_IS_PARAM_SPEC (param));
    1539                 :             : 
    1540                 :           2 :   if (value->data[0].v_pointer)
    1541                 :           1 :     g_param_spec_unref (value->data[0].v_pointer);
    1542                 :           2 :   value->data[0].v_pointer = param;
    1543                 :           2 :   if (value->data[0].v_pointer)
    1544                 :           2 :     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                 :           0 : g_value_set_param_take_ownership (GValue     *value,
    1558                 :             :                                   GParamSpec *param)
    1559                 :             : {
    1560                 :           0 :   g_value_take_param (value, param);
    1561                 :           0 : }
    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                 :           2 : g_value_take_param (GValue     *value,
    1576                 :             :                     GParamSpec *param)
    1577                 :             : {
    1578                 :           2 :   g_return_if_fail (G_VALUE_HOLDS_PARAM (value));
    1579                 :           2 :   if (param)
    1580                 :           2 :     g_return_if_fail (G_IS_PARAM_SPEC (param));
    1581                 :             : 
    1582                 :           2 :   if (value->data[0].v_pointer)
    1583                 :           0 :     g_param_spec_unref (value->data[0].v_pointer);
    1584                 :           2 :   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                 :     2899120 : g_value_get_param (const GValue *value)
    1597                 :             : {
    1598                 :     2899120 :   g_return_val_if_fail (G_VALUE_HOLDS_PARAM (value), NULL);
    1599                 :             : 
    1600                 :     2899120 :   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                 :           1 : g_value_dup_param (const GValue *value)
    1615                 :             : {
    1616                 :           1 :   g_return_val_if_fail (G_VALUE_HOLDS_PARAM (value), NULL);
    1617                 :             : 
    1618                 :           1 :   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                 :      172987 : g_param_spec_get_default_value (GParamSpec *pspec)
    1635                 :             : {
    1636                 :      172987 :   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                 :      172987 :   if (g_once_init_enter_pointer (&priv->default_value.g_type))
    1652                 :             :     {
    1653                 :        2858 :       GValue default_value = G_VALUE_INIT;
    1654                 :             : 
    1655                 :        2858 :       g_value_init (&default_value, pspec->value_type);
    1656                 :        2858 :       g_param_value_set_default (pspec, &default_value);
    1657                 :             : 
    1658                 :             :       /* store all but the type */
    1659                 :        2858 :       memcpy (priv->default_value.data, default_value.data, sizeof (default_value.data));
    1660                 :             : 
    1661                 :        2858 :       g_once_init_leave_pointer (&priv->default_value.g_type, pspec->value_type);
    1662                 :             :     }
    1663                 :             : 
    1664                 :      172987 :   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                 :     3059435 : g_param_spec_get_name_quark (GParamSpec *pspec)
    1679                 :             : {
    1680                 :     3059435 :   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                 :     3059435 :   return priv->name_quark;
    1688                 :             : }
        

Generated by: LCOV version 2.0-1