LCOV - code coverage report
Current view: top level - glib/gobject - gparam.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 424 513 82.7 %
Date: 2024-04-23 05:16:05 Functions: 51 62 82.3 %
Branches: 154 234 65.8 %

           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                 :    4837251 : g_param_spec_get_private (GParamSpec *pspec)
      95                 :            : {
      96                 :    4837251 :   return &G_STRUCT_MEMBER (GParamSpecPrivate, pspec, g_param_private_offset);
      97                 :            : }
      98                 :            : 
      99                 :            : void
     100                 :        527 : _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                 :        527 :   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                 :        527 :   type = g_type_register_fundamental (G_TYPE_PARAM, g_intern_static_string ("GParam"), &param_spec_info, &finfo, G_TYPE_FLAG_ABSTRACT);
     141                 :        527 :   g_assert (type == G_TYPE_PARAM);
     142                 :        527 :   g_param_private_offset = g_type_add_instance_private (type, sizeof (GParamSpecPrivate));
     143                 :        527 :   g_value_register_transform_func (G_TYPE_PARAM, G_TYPE_PARAM, value_param_transform_value);
     144                 :        527 : }
     145                 :            : 
     146                 :            : static void
     147                 :      11283 : g_param_spec_class_base_init (GParamSpecClass *class)
     148                 :            : {
     149                 :      11283 : }
     150                 :            : 
     151                 :            : static void
     152                 :          0 : g_param_spec_class_base_finalize (GParamSpecClass *class)
     153                 :            : {
     154                 :          0 : }
     155                 :            : 
     156                 :            : static void
     157                 :        527 : g_param_spec_class_init (GParamSpecClass *class,
     158                 :            :                          gpointer         class_data)
     159                 :            : {
     160                 :        527 :   class->value_type = G_TYPE_NONE;
     161                 :        527 :   class->finalize = g_param_spec_finalize;
     162                 :        527 :   class->value_set_default = NULL;
     163                 :        527 :   class->value_validate = NULL;
     164                 :        527 :   class->values_cmp = NULL;
     165                 :            : 
     166                 :        527 :   g_type_class_adjust_private_offset (class, &g_param_private_offset);
     167                 :        527 : }
     168                 :            : 
     169                 :            : static void
     170                 :      10826 : g_param_spec_init (GParamSpec      *pspec,
     171                 :            :                    GParamSpecClass *class)
     172                 :            : {
     173                 :      10826 :   pspec->name = NULL;
     174                 :      10826 :   pspec->_nick = NULL;
     175                 :      10826 :   pspec->_blurb = NULL;
     176                 :      10826 :   pspec->flags = 0;
     177                 :      10826 :   pspec->value_type = class->value_type;
     178                 :      10826 :   pspec->owner_type = 0;
     179                 :      10826 :   pspec->qdata = NULL;
     180                 :      10826 :   g_datalist_set_flags (&pspec->qdata, PARAM_FLOATING_FLAG);
     181                 :      10826 :   pspec->ref_count = 1;
     182                 :      10826 :   pspec->param_id = 0;
     183                 :      10826 : }
     184                 :            : 
     185                 :            : static void
     186                 :         41 : g_param_spec_finalize (GParamSpec *pspec)
     187                 :            : {
     188                 :         41 :   GParamSpecPrivate *priv = g_param_spec_get_private (pspec);
     189                 :            : 
     190         [ +  + ]:         41 :   if (priv->default_value.g_type)
     191                 :          1 :     g_value_reset (&priv->default_value);
     192                 :            : 
     193                 :         41 :   g_datalist_clear (&pspec->qdata);
     194                 :            : 
     195         [ +  - ]:         41 :   if (!(pspec->flags & G_PARAM_STATIC_NICK))
     196                 :         41 :     g_free (pspec->_nick);
     197                 :            : 
     198         [ +  - ]:         41 :   if (!(pspec->flags & G_PARAM_STATIC_BLURB))
     199                 :         41 :     g_free (pspec->_blurb);
     200                 :            : 
     201                 :         41 :   g_type_free_instance ((GTypeInstance*) pspec);
     202                 :         41 : }
     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                 :    4628045 : g_param_spec_ref (GParamSpec *pspec)
     214                 :            : {
     215                 :    4628045 :   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
     216                 :            : 
     217                 :    4628045 :   g_atomic_int_inc ((int *)&pspec->ref_count);
     218                 :            : 
     219                 :    4628045 :   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                 :    4616255 : g_param_spec_unref (GParamSpec *pspec)
     230                 :            : {
     231                 :            :   gboolean is_zero;
     232                 :            : 
     233                 :    4616255 :   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
     234                 :            : 
     235                 :    4616255 :   is_zero = g_atomic_int_dec_and_test ((int *)&pspec->ref_count);
     236                 :            : 
     237         [ +  + ]:    4616255 :   if (G_UNLIKELY (is_zero))
     238                 :            :     {
     239                 :         41 :       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                 :      10786 : g_param_spec_ref_sink (GParamSpec *pspec)
     277                 :            : {
     278                 :            :   guintptr oldvalue;
     279                 :      10786 :   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
     280                 :            : 
     281                 :      10786 :   oldvalue = g_atomic_pointer_and (&pspec->qdata, ~(gsize)PARAM_FLOATING_FLAG);
     282         [ -  + ]:      10786 :   if (!(oldvalue & PARAM_FLOATING_FLAG))
     283                 :          0 :     g_param_spec_ref (pspec);
     284                 :            : 
     285                 :      10786 :   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                 :         53 : canonicalize_key (gchar *key)
     365                 :            : {
     366                 :            :   gchar *p;
     367                 :            :   
     368         [ +  + ]:        480 :   for (p = key; *p != 0; p++)
     369                 :            :     {
     370                 :        427 :       gchar c = *p;
     371                 :            :       
     372         [ +  + ]:        427 :       if (c == '_')
     373                 :         53 :         *p = '-';
     374                 :            :     }
     375                 :         53 : }
     376                 :            : 
     377                 :            : /* @key must have already been validated with is_valid() */
     378                 :            : static gboolean
     379                 :      43037 : is_canonical (const gchar *key)
     380                 :            : {
     381                 :      43037 :   return (strchr (key, '_') == NULL);
     382                 :            : }
     383                 :            : 
     384                 :            : /**
     385                 :            :  * g_param_spec_is_valid_name:
     386                 :            :  * @name: the canonical name of the property
     387                 :            :  *
     388                 :            :  * Validate a property name for a #GParamSpec. This can be useful for
     389                 :            :  * dynamically-generated properties which need to be validated at run-time
     390                 :            :  * before actually trying to create them.
     391                 :            :  *
     392                 :            :  * See [canonical parameter names][canonical-parameter-names] for details of
     393                 :            :  * the rules for valid names.
     394                 :            :  *
     395                 :            :  * Returns: %TRUE if @name is a valid property name, %FALSE otherwise.
     396                 :            :  * Since: 2.66
     397                 :            :  */
     398                 :            : gboolean
     399                 :      12953 : g_param_spec_is_valid_name (const gchar *name)
     400                 :            : {
     401                 :            :   const gchar *p;
     402                 :            : 
     403                 :            :   /* First character must be a letter. */
     404   [ +  +  +  - ]:      12953 :   if ((name[0] < 'A' || name[0] > 'Z') &&
     405   [ +  +  -  + ]:      12953 :       (name[0] < 'a' || name[0] > 'z'))
     406                 :          4 :     return FALSE;
     407                 :            : 
     408         [ +  + ]:     142219 :   for (p = name; *p != 0; p++)
     409                 :            :     {
     410                 :     129272 :       const gchar c = *p;
     411                 :            : 
     412   [ +  +  +  +  :     129272 :       if (c != '-' && c != '_' &&
                   +  - ]
     413   [ +  +  +  + ]:     120428 :           (c < '0' || c > '9') &&
     414   [ +  +  +  + ]:     120269 :           (c < 'A' || c > 'Z') &&
     415         [ -  + ]:     120253 :           (c < 'a' || c > 'z'))
     416                 :          2 :         return FALSE;
     417                 :            :     }
     418                 :            : 
     419                 :      12947 :   return TRUE;
     420                 :            : }
     421                 :            : 
     422                 :            : /**
     423                 :            :  * g_param_spec_internal: (skip)
     424                 :            :  * @param_type: the #GType for the property; must be derived from %G_TYPE_PARAM
     425                 :            :  * @name: the canonical name of the property
     426                 :            :  * @nick: (nullable): the nickname of the property
     427                 :            :  * @blurb: (nullable): a short description of the property
     428                 :            :  * @flags: a combination of #GParamFlags
     429                 :            :  *
     430                 :            :  * Creates a new #GParamSpec instance.
     431                 :            :  *
     432                 :            :  * See [canonical parameter names][canonical-parameter-names] for details of
     433                 :            :  * the rules for @name. Names which violate these rules lead to undefined
     434                 :            :  * behaviour.
     435                 :            :  *
     436                 :            :  * Beyond the name, #GParamSpecs have two more descriptive strings, the
     437                 :            :  * @nick and @blurb, which may be used as a localized label and description.
     438                 :            :  * For GTK and related libraries these are considered deprecated and may be
     439                 :            :  * omitted, while for other libraries such as GStreamer and its plugins they
     440                 :            :  * are essential. When in doubt, follow the conventions used in the
     441                 :            :  * surrounding code and supporting libraries.
     442                 :            :  *
     443                 :            :  * Returns: (type GObject.ParamSpec): (transfer floating): a newly allocated
     444                 :            :  *     #GParamSpec instance, which is initially floating
     445                 :            :  */
     446                 :            : gpointer
     447                 :      10826 : 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                 :      10826 :   g_return_val_if_fail (G_TYPE_IS_PARAM (param_type) && param_type != G_TYPE_PARAM, NULL);
     457                 :      10826 :   g_return_val_if_fail (name != NULL, NULL);
     458                 :      10826 :   g_return_val_if_fail (g_param_spec_is_valid_name (name), NULL);
     459                 :      10826 :   g_return_val_if_fail (!(flags & G_PARAM_STATIC_NAME) || is_canonical (name), NULL);
     460                 :            :   
     461                 :      10826 :   pspec = (gpointer) g_type_create_instance (param_type);
     462                 :            : 
     463         [ +  + ]:      10826 :   if (flags & G_PARAM_STATIC_NAME)
     464                 :            :     {
     465                 :            :       /* pspec->name is not freed if (flags & G_PARAM_STATIC_NAME) */
     466                 :      10650 :       pspec->name = (gchar *) g_intern_static_string (name);
     467         [ -  + ]:      10650 :       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         [ +  + ]:        176 :       if (is_canonical (name))
     473                 :        175 :         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                 :      10826 :   priv = g_param_spec_get_private (pspec);
     484                 :      10826 :   priv->name_quark = g_quark_from_string (pspec->name);
     485                 :            : 
     486         [ +  + ]:      10826 :   if (flags & G_PARAM_STATIC_NICK)
     487                 :      10340 :     pspec->_nick = (gchar*) nick;
     488                 :            :   else
     489                 :        486 :     pspec->_nick = g_strdup (nick);
     490                 :            : 
     491         [ +  + ]:      10826 :   if (flags & G_PARAM_STATIC_BLURB)
     492                 :      10650 :     pspec->_blurb = (gchar*) blurb;
     493                 :            :   else
     494                 :        176 :     pspec->_blurb = g_strdup (blurb);
     495                 :            : 
     496                 :      10826 :   pspec->flags = (flags & G_PARAM_USER_MASK) | (flags & G_PARAM_MASK);
     497                 :            :   
     498                 :      10826 :   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                 :       1956 : g_param_spec_get_redirect_target (GParamSpec *pspec)
     610                 :            : {
     611                 :       1956 :   GTypeInstance *inst = (GTypeInstance *)pspec;
     612                 :            : 
     613   [ +  -  +  -  :       1956 :   if (inst && inst->g_class && inst->g_class->g_type == G_TYPE_PARAM_OVERRIDE)
                   +  + ]
     614                 :        144 :     return ((GParamSpecOverride*)pspec)->overridden;
     615                 :            :   else
     616                 :       1812 :     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                 :       2594 : g_param_value_set_default (GParamSpec *pspec,
     629                 :            :                            GValue     *value)
     630                 :            : {
     631                 :       2594 :   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
     632                 :            : 
     633         [ +  + ]:       2594 :   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                 :       2586 :       g_return_if_fail (G_IS_VALUE (value));
     640                 :       2586 :       g_return_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value));
     641                 :       2586 :       g_value_reset (value);
     642                 :            :     }
     643                 :            : 
     644                 :       2594 :   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                 :       6906 : g_param_value_validate (GParamSpec *pspec,
     691                 :            :                         GValue     *value)
     692                 :            : {
     693                 :       6906 :   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
     694                 :       6906 :   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
     695                 :       6906 :   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE);
     696                 :            : 
     697         [ +  - ]:       6906 :   if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate)
     698                 :            :     {
     699                 :       6906 :       GValue oval = *value;
     700                 :            : 
     701         [ +  + ]:       6906 :       if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate (pspec, value) ||
     702         [ -  + ]:       6872 :           memcmp (&oval.data, &value->data, sizeof (oval.data)))
     703                 :         34 :         return TRUE;
     704                 :            :     }
     705                 :            : 
     706                 :       6872 :   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                 :         45 : g_param_value_is_valid (GParamSpec *pspec,
     724                 :            :                         const GValue *value)
     725                 :            : {
     726                 :            :   GParamSpecClass *class;
     727                 :            : 
     728                 :         45 :   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), TRUE);
     729                 :         45 :   g_return_val_if_fail (G_IS_VALUE (value), TRUE);
     730                 :         45 :   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), TRUE);
     731                 :            : 
     732                 :         45 :   class = G_PARAM_SPEC_GET_CLASS (pspec);
     733                 :            : 
     734         [ +  + ]:         45 :   if (class->value_is_valid)
     735                 :         44 :     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                 :    4616809 : value_param_free_value (GValue *value)
     851                 :            : {
     852         [ +  # ]:    4616809 :   if (value->data[0].v_pointer)
     853                 :    4616873 :     g_param_spec_unref (value->data[0].v_pointer);
     854                 :    4616810 : }
     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                 :    4616342 : value_param_collect_value (GValue      *value,
     885                 :            :                            guint        n_collect_values,
     886                 :            :                            GTypeCValue *collect_values,
     887                 :            :                            guint        collect_flags)
     888                 :            : {
     889         [ +  # ]:    4616342 :   if (collect_values[0].v_pointer)
     890                 :            :     {
     891                 :    4616734 :       GParamSpec *param = collect_values[0].v_pointer;
     892                 :            : 
     893         [ -  + ]:    4616734 :       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         [ -  + ]:    4616734 :       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                 :    4616656 :       value->data[0].v_pointer = g_param_spec_ref (param);
     906                 :            :     }
     907                 :            :   else
     908                 :          0 :     value->data[0].v_pointer = NULL;
     909                 :            : 
     910                 :    4616237 :   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                 :   44787127 : param_spec_pool_hash (gconstpointer key_spec)
     953                 :            : {
     954                 :   44787127 :   const GParamSpec *key = key_spec;
     955                 :            :   const gchar *p;
     956                 :   44787127 :   guint h = (guint) key->owner_type;
     957                 :            : 
     958         [ +  + ]:  318693820 :   for (p = key->name; *p; p++)
     959                 :  273906693 :     h = (h << 5) - h + *p;
     960                 :            : 
     961                 :   44787127 :   return h;
     962                 :            : }
     963                 :            : 
     964                 :            : static gboolean
     965                 :   44725761 : param_spec_pool_equals (gconstpointer key_spec_1,
     966                 :            :                         gconstpointer key_spec_2)
     967                 :            : {
     968                 :   44725761 :   const GParamSpec *key1 = key_spec_1;
     969                 :   44725761 :   const GParamSpec *key2 = key_spec_2;
     970                 :            : 
     971         [ +  - ]:   89451522 :   return (key1->owner_type == key2->owner_type &&
     972         [ +  + ]:   44725761 :           (key1->name == key2->name ||
     973         [ +  - ]:   44348313 :            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                 :        322 : g_param_spec_pool_new (gboolean type_prefixing)
     991                 :            : {
     992                 :            :   static GMutex init_mutex;
     993                 :        322 :   GParamSpecPool *pool = g_new (GParamSpecPool, 1);
     994                 :            : 
     995                 :        322 :   memcpy (&pool->mutex, &init_mutex, sizeof (init_mutex));
     996                 :        322 :   pool->type_prefixing = type_prefixing != FALSE;
     997                 :        322 :   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                 :        322 :   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                 :      10785 : g_param_spec_pool_insert (GParamSpecPool *pool,
    1033                 :            :                           GParamSpec     *pspec,
    1034                 :            :                           GType           owner_type)
    1035                 :            : {
    1036                 :            :   const gchar *p;
    1037                 :            :   
    1038   [ +  -  +  -  :      10785 :   if (pool && pspec && owner_type > 0 && pspec->owner_type == 0)
             +  -  +  - ]
    1039                 :            :     {
    1040         [ +  + ]:     117258 :       for (p = pspec->name; *p; p++)
    1041                 :            :         {
    1042         [ -  + ]:     106473 :           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                 :      10785 :       g_mutex_lock (&pool->mutex);
    1049                 :      10785 :       pspec->owner_type = owner_type;
    1050                 :      10785 :       g_param_spec_ref (pspec);
    1051                 :      10785 :       g_hash_table_add (pool->hash_table, pspec);
    1052                 :      10785 :       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                 :   44747269 : 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                 :   44747269 :   key.owner_type = owner_type;
    1097                 :   44747269 :   key.name = (gchar*) param_name;
    1098         [ +  + ]:   44747269 :   if (walk_ancestors)
    1099                 :            :     do
    1100                 :            :       {
    1101                 :   44765017 :         pspec = g_hash_table_lookup (hash_table, &key);
    1102         [ +  + ]:   44765017 :         if (pspec)
    1103                 :   44725261 :           return pspec;
    1104                 :      39756 :         key.owner_type = g_type_parent (key.owner_type);
    1105                 :            :       }
    1106         [ +  + ]:      39756 :     while (key.owner_type);
    1107                 :            :   else
    1108                 :      11272 :     pspec = g_hash_table_lookup (hash_table, &key);
    1109                 :            : 
    1110   [ +  +  +  + ]:      22008 :   if (!pspec && !is_canonical (param_name))
    1111                 :            :     {
    1112                 :            :       gchar *canonical;
    1113                 :            : 
    1114                 :         52 :       canonical = g_strdup (key.name);
    1115                 :         52 :       canonicalize_key (canonical);
    1116                 :            : 
    1117                 :            :       /* try canonicalized form */
    1118                 :         52 :       key.name = canonical;
    1119                 :         52 :       key.owner_type = owner_type;
    1120                 :            : 
    1121         [ +  - ]:         52 :       if (walk_ancestors)
    1122                 :            :         do
    1123                 :            :           {
    1124                 :         52 :             pspec = g_hash_table_lookup (hash_table, &key);
    1125         [ +  - ]:         52 :             if (pspec)
    1126                 :            :               {
    1127                 :         52 :                 g_free (canonical);
    1128                 :         52 :                 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                 :      21956 :   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                 :   44291656 : 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                 :   44291656 :   g_return_val_if_fail (pool != NULL, NULL);
    1164                 :   44291656 :   g_return_val_if_fail (param_name != NULL, NULL);
    1165                 :            : 
    1166                 :   44291656 :   g_mutex_lock (&pool->mutex);
    1167                 :            : 
    1168                 :            :   /* try quick and away, i.e. without prefix */
    1169                 :   44746122 :   pspec = param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
    1170         [ +  + ]:   44746122 :   if (pspec)
    1171                 :            :     {
    1172                 :   44724613 :       g_mutex_unlock (&pool->mutex);
    1173                 :   44663556 :       return pspec;
    1174                 :            :     }
    1175                 :            : 
    1176         [ +  + ]:      21509 :   if (pool->type_prefixing)
    1177                 :            :     {
    1178                 :            :       char *delim;
    1179                 :            : 
    1180                 :      21508 :       delim = strchr (param_name, ':');
    1181                 :            : 
    1182                 :            :       /* strip type prefix */
    1183   [ -  +  -  - ]:      21508 :       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                 :      21509 :   g_mutex_unlock (&pool->mutex);
    1216                 :            : 
    1217                 :      21509 :   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                 :       2021 : pspec_compare_id (gconstpointer a,
    1265                 :            :                   gconstpointer b)
    1266                 :            : {
    1267                 :       2021 :   const GParamSpec *pspec1 = a, *pspec2 = b;
    1268                 :            : 
    1269         [ +  + ]:       2021 :   if (pspec1->param_id < pspec2->param_id)
    1270                 :        240 :     return -1;
    1271                 :            : 
    1272         [ +  + ]:       1781 :   if (pspec1->param_id > pspec2->param_id)
    1273                 :        283 :     return 1;
    1274                 :            : 
    1275                 :       1498 :   return strcmp (pspec1->name, pspec2->name);
    1276                 :            : }
    1277                 :            : 
    1278                 :            : static inline gboolean
    1279                 :       1152 : 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         [ +  + ]:       1152 :   if (g_param_spec_get_redirect_target (pspec))
    1291                 :          5 :     return FALSE;
    1292                 :            : 
    1293                 :       1147 :   found = param_spec_ht_lookup (ht, pspec->name, owner_type, TRUE);
    1294         [ +  + ]:       1147 :   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                 :       1129 :   return TRUE;
    1302                 :            : }
    1303                 :            : 
    1304                 :            : static void
    1305                 :      17188 : pool_depth_list (gpointer key,
    1306                 :            :                  gpointer value,
    1307                 :            :                  gpointer user_data)
    1308                 :            : {
    1309                 :      17188 :   GParamSpec *pspec = value;
    1310                 :      17188 :   gpointer *data = user_data;
    1311                 :      17188 :   GSList **slists = data[0];
    1312                 :      17188 :   GType owner_type = (GType) data[1];
    1313                 :      17188 :   GHashTable *ht = data[2];
    1314                 :      17188 :   int *count = data[3];
    1315                 :            : 
    1316   [ +  +  +  +  :      17615 :   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                 :      17188 : }
    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                 :     108559 : pool_depth_list_for_interface (gpointer key,
    1345                 :            :                                gpointer value,
    1346                 :            :                                gpointer user_data)
    1347                 :            : {
    1348                 :     108559 :   GParamSpec *pspec = value;
    1349                 :     108559 :   gpointer *data = user_data;
    1350                 :     108559 :   GSList **slists = data[0];
    1351                 :     108559 :   GType owner_type = (GType) data[1];
    1352                 :     108559 :   GHashTable *ht = data[2];
    1353                 :     108559 :   int *count = data[3];
    1354                 :            : 
    1355   [ +  +  +  - ]:     109284 :   if (pspec->owner_type == owner_type &&
    1356                 :        725 :       should_list_pspec (pspec, owner_type, ht))
    1357                 :            :     {
    1358                 :        725 :       slists[0] = g_slist_prepend (slists[0], pspec);
    1359                 :        725 :       *count = *count + 1;
    1360                 :            :     }
    1361                 :     108559 : }
    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                 :       3171 : 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                 :       3171 :   int n_pspecs = 0;
    1386                 :            : 
    1387                 :       3171 :   g_return_val_if_fail (pool != NULL, NULL);
    1388                 :       3171 :   g_return_val_if_fail (owner_type > 0, NULL);
    1389                 :       3171 :   g_return_val_if_fail (n_pspecs_p != NULL, NULL);
    1390                 :            :   
    1391                 :       3171 :   g_mutex_lock (&pool->mutex);
    1392                 :       3171 :   d = g_type_depth (owner_type);
    1393                 :       3171 :   slists = g_new0 (GSList*, d);
    1394                 :       3171 :   data[0] = slists;
    1395                 :       3171 :   data[1] = GTYPE_TO_POINTER (owner_type);
    1396                 :       3171 :   data[2] = pool->hash_table;
    1397                 :       3171 :   data[3] = &n_pspecs;
    1398                 :            : 
    1399         [ +  + ]:       3171 :   g_hash_table_foreach (pool->hash_table,
    1400                 :       3171 :                         G_TYPE_IS_INTERFACE (owner_type) ?
    1401                 :            :                           pool_depth_list_for_interface :
    1402                 :            :                           pool_depth_list,
    1403                 :            :                         &data);
    1404                 :            : 
    1405                 :       3171 :   pspecs = g_new (GParamSpec*, n_pspecs + 1);
    1406                 :       3171 :   p = pspecs;
    1407         [ +  + ]:       9576 :   for (i = 0; i < d; i++)
    1408                 :            :     {
    1409                 :       6405 :       slists[i] = g_slist_sort (slists[i], pspec_compare_id);
    1410         [ +  + ]:       7534 :       for (node = slists[i]; node; node = node->next)
    1411                 :       1129 :         *p++ = node->data;
    1412                 :       6405 :       g_slist_free (slists[i]);
    1413                 :            :     }
    1414                 :       3171 :   *p++ = NULL;
    1415                 :       3171 :   g_free (slists);
    1416                 :       3171 :   g_mutex_unlock (&pool->mutex);
    1417                 :            : 
    1418                 :       3171 :   *n_pspecs_p = n_pspecs;
    1419                 :            : 
    1420                 :       3171 :   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                 :      10756 : param_spec_generic_class_init (gpointer g_class,
    1440                 :            :                                gpointer class_data)
    1441                 :            : {
    1442                 :      10756 :   GParamSpecClass *class = g_class;
    1443                 :      10756 :   ParamSpecClassInfo *info = class_data;
    1444                 :            : 
    1445                 :      10756 :   class->value_type = info->value_type;
    1446         [ +  + ]:      10756 :   if (info->finalize)
    1447                 :       2635 :     class->finalize = info->finalize;                     /* optional */
    1448                 :      10756 :   class->value_set_default = info->value_set_default;
    1449         [ +  + ]:      10756 :   if (info->value_validate)
    1450                 :      10541 :     class->value_validate = info->value_validate; /* optional */
    1451                 :      10756 :   class->values_cmp = info->values_cmp;
    1452                 :      10756 :   g_free (class_data);
    1453                 :      10756 : }
    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                 :      12122 : g_param_type_register_static (const gchar              *name,
    1486                 :            :                               const GParamSpecTypeInfo *pspec_info)
    1487                 :            : {
    1488                 :      12122 :   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                 :      12122 :   g_return_val_if_fail (name != NULL, 0);
    1503                 :      12122 :   g_return_val_if_fail (pspec_info != NULL, 0);
    1504                 :      12122 :   g_return_val_if_fail (g_type_from_name (name) == 0, 0);
    1505                 :      12122 :   g_return_val_if_fail (pspec_info->instance_size >= sizeof (GParamSpec), 0);
    1506                 :      12122 :   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                 :      12122 :   info.instance_size = pspec_info->instance_size;
    1512                 :      12122 :   info.n_preallocs = pspec_info->n_preallocs;
    1513                 :      12122 :   info.instance_init = (GInstanceInitFunc) pspec_info->instance_init;
    1514                 :      12122 :   cinfo = g_new (ParamSpecClassInfo, 1);
    1515                 :      12122 :   cinfo->value_type = pspec_info->value_type;
    1516                 :      12122 :   cinfo->finalize = pspec_info->finalize;
    1517         [ +  - ]:      12122 :   cinfo->value_set_default = pspec_info->value_set_default ? pspec_info->value_set_default : default_value_set_default;
    1518                 :      12122 :   cinfo->value_validate = pspec_info->value_validate;
    1519         [ +  - ]:      12122 :   cinfo->values_cmp = pspec_info->values_cmp ? pspec_info->values_cmp : default_values_cmp;
    1520                 :      12122 :   info.class_data = cinfo;
    1521                 :            : 
    1522                 :      12122 :   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                 :    4570467 : g_value_get_param (const GValue *value)
    1597                 :            : {
    1598                 :    4570467 :   g_return_val_if_fail (G_VALUE_HOLDS_PARAM (value), NULL);
    1599                 :            : 
    1600                 :    4570467 :   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                 :     211750 : g_param_spec_get_default_value (GParamSpec *pspec)
    1635                 :            : {
    1636                 :     211750 :   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   [ +  +  +  -  :     211750 :   if (g_once_init_enter_pointer (&priv->default_value.g_type))
                   +  + ]
    1652                 :            :     {
    1653                 :       2547 :       GValue default_value = G_VALUE_INIT;
    1654                 :            : 
    1655                 :       2547 :       g_value_init (&default_value, pspec->value_type);
    1656                 :       2547 :       g_param_value_set_default (pspec, &default_value);
    1657                 :            : 
    1658                 :            :       /* store all but the type */
    1659                 :       2547 :       memcpy (priv->default_value.data, default_value.data, sizeof (default_value.data));
    1660                 :            : 
    1661                 :       2547 :       g_once_init_leave_pointer (&priv->default_value.g_type, pspec->value_type);
    1662                 :            :     }
    1663                 :            : 
    1664                 :     211749 :   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                 :    4616853 : g_param_spec_get_name_quark (GParamSpec *pspec)
    1679                 :            : {
    1680                 :    4616853 :   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                 :    4616858 :   return priv->name_quark;
    1688                 :            : }

Generated by: LCOV version 1.14