glib/libgobject/src/gparam.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /* GObject - GLib Type, Object, Parameter and Signal Library
       
     2  * Copyright (C) 1997-1999, 2000-2001 Tim Janik and Red Hat, Inc.
       
     3  * Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
       
     4  *
       
     5  * This library is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU Lesser General Public
       
     7  * License as published by the Free Software Foundation; either
       
     8  * version 2 of the License, or (at your option) any later version.
       
     9  *
       
    10  * This library is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13  * Lesser General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU Lesser General
       
    16  * Public License along with this library; if not, write to the
       
    17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
       
    18  * Boston, MA 02111-1307, USA.
       
    19  */
       
    20 
       
    21 /*
       
    22  * MT safe
       
    23  */
       
    24 
       
    25 #include	"gparam.h"
       
    26 #include        "gparamspecs.h"
       
    27 
       
    28 #include	"gvaluecollector.h"
       
    29 #include	"gobjectalias.h"
       
    30 #include	<string.h>
       
    31 
       
    32 #ifdef __SYMBIAN32__
       
    33 #include <glib_global.h>
       
    34 #include <gobject_wsd.h>
       
    35 #include <gobject_global.h>
       
    36 #endif /* __SYMBIAN32__ */
       
    37 
       
    38 
       
    39 
       
    40 /* --- defines --- */
       
    41 #define	G_PARAM_USER_MASK			(~0 << G_PARAM_USER_SHIFT)
       
    42 #define PSPEC_APPLIES_TO_VALUE(pspec, value)	(G_TYPE_CHECK_VALUE_TYPE ((value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
       
    43 #define	G_SLOCK(mutex)				g_static_mutex_lock (mutex)
       
    44 #define	G_SUNLOCK(mutex)			g_static_mutex_unlock (mutex)
       
    45 
       
    46 
       
    47 /* --- prototypes --- */
       
    48 static void	g_param_spec_class_base_init	 (GParamSpecClass	*class);
       
    49 static void	g_param_spec_class_base_finalize (GParamSpecClass	*class);
       
    50 static void	g_param_spec_class_init		 (GParamSpecClass	*class,
       
    51 						  gpointer               class_data);
       
    52 static void	g_param_spec_init		 (GParamSpec		*pspec,
       
    53 						  GParamSpecClass	*class);
       
    54 static void	g_param_spec_finalize		 (GParamSpec		*pspec);
       
    55 static void	value_param_init		(GValue		*value);
       
    56 static void	value_param_free_value		(GValue		*value);
       
    57 static void	value_param_copy_value		(const GValue	*src_value,
       
    58 						 GValue		*dest_value);
       
    59 static void	value_param_transform_value	(const GValue	*src_value,
       
    60 						 GValue		*dest_value);
       
    61 static gpointer	value_param_peek_pointer	(const GValue	*value);
       
    62 static gchar*	value_param_collect_value	(GValue		*value,
       
    63 						 guint           n_collect_values,
       
    64 						 GTypeCValue    *collect_values,
       
    65 						 guint           collect_flags);
       
    66 static gchar*	value_param_lcopy_value		(const GValue	*value,
       
    67 						 guint           n_collect_values,
       
    68 						 GTypeCValue    *collect_values,
       
    69 						 guint           collect_flags);
       
    70 
       
    71 
       
    72 /* --- variables --- */
       
    73 #if EMULATOR
       
    74 
       
    75 PLS(quark_floating ,gparam,GQuark)
       
    76 #define quark_floating  (*FUNCTION_NAME(quark_floating ,gparam)())
       
    77 
       
    78 #else
       
    79 
       
    80 static GQuark quark_floating = 0;
       
    81 
       
    82 #endif /* EMULATOR */
       
    83 /* --- functions --- */
       
    84 void
       
    85 g_param_type_init (void)
       
    86 {
       
    87   static const GTypeFundamentalInfo finfo = {
       
    88     (G_TYPE_FLAG_CLASSED |
       
    89      G_TYPE_FLAG_INSTANTIATABLE |
       
    90      G_TYPE_FLAG_DERIVABLE |
       
    91      G_TYPE_FLAG_DEEP_DERIVABLE),
       
    92   };
       
    93   static const GTypeValueTable param_value_table = {
       
    94     value_param_init,           /* value_init */
       
    95     value_param_free_value,     /* value_free */
       
    96     value_param_copy_value,     /* value_copy */
       
    97     value_param_peek_pointer,   /* value_peek_pointer */
       
    98     "p",			/* collect_format */
       
    99     value_param_collect_value,  /* collect_value */
       
   100     "p",			/* lcopy_format */
       
   101     value_param_lcopy_value,    /* lcopy_value */
       
   102   };
       
   103   static const GTypeInfo param_spec_info = {
       
   104     sizeof (GParamSpecClass),
       
   105 
       
   106     (GBaseInitFunc) g_param_spec_class_base_init,
       
   107     (GBaseFinalizeFunc) g_param_spec_class_base_finalize,
       
   108     (GClassInitFunc) g_param_spec_class_init,
       
   109     (GClassFinalizeFunc) NULL,
       
   110     NULL,	/* class_data */
       
   111 
       
   112     sizeof (GParamSpec),
       
   113     0,		/* n_preallocs */
       
   114     (GInstanceInitFunc) g_param_spec_init,
       
   115 
       
   116     &param_value_table,
       
   117   };
       
   118   GType type;
       
   119 
       
   120   type = g_type_register_fundamental (G_TYPE_PARAM, g_intern_static_string ("GParam"), &param_spec_info, &finfo, G_TYPE_FLAG_ABSTRACT);
       
   121   g_assert (type == G_TYPE_PARAM);
       
   122   g_value_register_transform_func (G_TYPE_PARAM, G_TYPE_PARAM, value_param_transform_value);
       
   123 }
       
   124 
       
   125 static void
       
   126 g_param_spec_class_base_init (GParamSpecClass *class)
       
   127 {
       
   128 }
       
   129 
       
   130 static void
       
   131 g_param_spec_class_base_finalize (GParamSpecClass *class)
       
   132 {
       
   133 }
       
   134 
       
   135 static void
       
   136 g_param_spec_class_init (GParamSpecClass *class,
       
   137 			 gpointer         class_data)
       
   138 {
       
   139   quark_floating = g_quark_from_static_string ("GParamSpec-floating");
       
   140 
       
   141   class->value_type = G_TYPE_NONE;
       
   142   class->finalize = g_param_spec_finalize;
       
   143   class->value_set_default = NULL;
       
   144   class->value_validate = NULL;
       
   145   class->values_cmp = NULL;
       
   146 }
       
   147 
       
   148 static void
       
   149 g_param_spec_init (GParamSpec      *pspec,
       
   150 		   GParamSpecClass *class)
       
   151 {
       
   152   pspec->name = NULL;
       
   153   pspec->_nick = NULL;
       
   154   pspec->_blurb = NULL;
       
   155   pspec->flags = 0;
       
   156   pspec->value_type = class->value_type;
       
   157   pspec->owner_type = 0;
       
   158   pspec->qdata = NULL;
       
   159   pspec->ref_count = 1;
       
   160   pspec->param_id = 0;
       
   161   g_datalist_id_set_data (&pspec->qdata, quark_floating, GUINT_TO_POINTER (TRUE));
       
   162 }
       
   163 
       
   164 static void
       
   165 g_param_spec_finalize (GParamSpec *pspec)
       
   166 {
       
   167   g_datalist_clear (&pspec->qdata);
       
   168 
       
   169   if (!(pspec->flags & G_PARAM_STATIC_NAME))
       
   170     g_free (pspec->name);
       
   171   
       
   172   if (!(pspec->flags & G_PARAM_STATIC_NICK))
       
   173     g_free (pspec->_nick);
       
   174 
       
   175   if (!(pspec->flags & G_PARAM_STATIC_BLURB))
       
   176     g_free (pspec->_blurb);
       
   177 
       
   178   g_type_free_instance ((GTypeInstance*) pspec);
       
   179 }
       
   180 
       
   181 EXPORT_C GParamSpec*
       
   182 g_param_spec_ref (GParamSpec *pspec)
       
   183 {
       
   184   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
       
   185   g_return_val_if_fail (pspec->ref_count > 0, NULL);
       
   186 
       
   187   g_atomic_int_inc (FIX_CASTING(int *)&pspec->ref_count);
       
   188 
       
   189   return pspec;
       
   190 }
       
   191 
       
   192 EXPORT_C void
       
   193 g_param_spec_unref (GParamSpec *pspec)
       
   194 {
       
   195   gboolean is_zero;
       
   196 
       
   197   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
       
   198   g_return_if_fail (pspec->ref_count > 0);
       
   199 
       
   200   is_zero = g_atomic_int_dec_and_test (FIX_CASTING(int *)&pspec->ref_count);
       
   201 
       
   202   if (G_UNLIKELY (is_zero))
       
   203     {
       
   204       G_PARAM_SPEC_GET_CLASS (pspec)->finalize (pspec);
       
   205     }
       
   206 }
       
   207 
       
   208 EXPORT_C void
       
   209 g_param_spec_sink (GParamSpec *pspec)
       
   210 {
       
   211   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
       
   212   g_return_if_fail (pspec->ref_count > 0);
       
   213 
       
   214   if (g_datalist_id_remove_no_notify (&pspec->qdata, quark_floating))
       
   215     g_param_spec_unref (pspec);
       
   216 }
       
   217 
       
   218 EXPORT_C GParamSpec*
       
   219 g_param_spec_ref_sink (GParamSpec *pspec)
       
   220 {
       
   221   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
       
   222   g_return_val_if_fail (pspec->ref_count > 0, NULL);
       
   223 
       
   224   g_param_spec_ref (pspec);
       
   225   g_param_spec_sink (pspec);
       
   226   return pspec;
       
   227 }
       
   228 
       
   229 EXPORT_C G_CONST_RETURN gchar*
       
   230 g_param_spec_get_name (GParamSpec *pspec)
       
   231 {
       
   232   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
       
   233 
       
   234   return pspec->name;
       
   235 }
       
   236 
       
   237 EXPORT_C G_CONST_RETURN gchar*
       
   238 g_param_spec_get_nick (GParamSpec *pspec)
       
   239 {
       
   240   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
       
   241 
       
   242   if (pspec->_nick)
       
   243     return pspec->_nick;
       
   244   else
       
   245     {
       
   246       GParamSpec *redirect_target;
       
   247 
       
   248       redirect_target = g_param_spec_get_redirect_target (pspec);
       
   249       if (redirect_target && redirect_target->_nick)
       
   250 	return redirect_target->_nick;
       
   251     }
       
   252 
       
   253   return pspec->name;
       
   254 }
       
   255 
       
   256 EXPORT_C G_CONST_RETURN gchar*
       
   257 g_param_spec_get_blurb (GParamSpec *pspec)
       
   258 {
       
   259   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
       
   260 
       
   261   if (pspec->_blurb)
       
   262     return pspec->_blurb;
       
   263   else
       
   264     {
       
   265       GParamSpec *redirect_target;
       
   266 
       
   267       redirect_target = g_param_spec_get_redirect_target (pspec);
       
   268       if (redirect_target && redirect_target->_blurb)
       
   269 	return redirect_target->_blurb;
       
   270     }
       
   271 
       
   272   return NULL;
       
   273 }
       
   274 
       
   275 static void
       
   276 canonicalize_key (gchar *key)
       
   277 {
       
   278   gchar *p;
       
   279   
       
   280   for (p = key; *p != 0; p++)
       
   281     {
       
   282       gchar c = *p;
       
   283       
       
   284       if (c != '-' &&
       
   285 	  (c < '0' || c > '9') &&
       
   286 	  (c < 'A' || c > 'Z') &&
       
   287 	  (c < 'a' || c > 'z'))
       
   288 	*p = '-';
       
   289     }
       
   290 }
       
   291 
       
   292 static gboolean
       
   293 is_canonical (const gchar *key)
       
   294 {
       
   295   const gchar *p;
       
   296 
       
   297   for (p = key; *p != 0; p++)
       
   298     {
       
   299       gchar c = *p;
       
   300       
       
   301       if (c != '-' &&
       
   302 	  (c < '0' || c > '9') &&
       
   303 	  (c < 'A' || c > 'Z') &&
       
   304 	  (c < 'a' || c > 'z'))
       
   305 	return FALSE;
       
   306     }
       
   307 
       
   308   return TRUE;
       
   309 }
       
   310 
       
   311 EXPORT_C gpointer
       
   312 g_param_spec_internal (GType        param_type,
       
   313 		       const gchar *name,
       
   314 		       const gchar *nick,
       
   315 		       const gchar *blurb,
       
   316 		       GParamFlags  flags)
       
   317 {
       
   318   GParamSpec *pspec;
       
   319   
       
   320   g_return_val_if_fail (G_TYPE_IS_PARAM (param_type) && param_type != G_TYPE_PARAM, NULL);
       
   321   g_return_val_if_fail (name != NULL, NULL);
       
   322   g_return_val_if_fail ((name[0] >= 'A' && name[0] <= 'Z') || (name[0] >= 'a' && name[0] <= 'z'), NULL);
       
   323   g_return_val_if_fail (!(flags & G_PARAM_STATIC_NAME) || is_canonical (name), NULL);
       
   324   
       
   325   pspec = (gpointer) g_type_create_instance (param_type);
       
   326 
       
   327   if (flags & G_PARAM_STATIC_NAME)
       
   328     {
       
   329       pspec->name = FIX_CASTING(char *)g_intern_static_string (name);
       
   330       if (!is_canonical (pspec->name))
       
   331         g_warning ("G_PARAM_STATIC_NAME used with non-canonical pspec name: %s", pspec->name);
       
   332     }
       
   333   else
       
   334     {
       
   335       pspec->name = g_strdup (name);
       
   336       canonicalize_key (pspec->name);
       
   337       g_intern_string (pspec->name);
       
   338     }
       
   339 
       
   340   if (flags & G_PARAM_STATIC_NICK)
       
   341     pspec->_nick = (gchar*) nick;
       
   342   else
       
   343     pspec->_nick = g_strdup (nick);
       
   344 
       
   345   if (flags & G_PARAM_STATIC_BLURB)
       
   346     pspec->_blurb = (gchar*) blurb;
       
   347   else
       
   348     pspec->_blurb = g_strdup (blurb);
       
   349 
       
   350   pspec->flags = (flags & G_PARAM_USER_MASK) | (flags & G_PARAM_MASK);
       
   351   
       
   352   return pspec;
       
   353 }
       
   354 
       
   355 EXPORT_C gpointer
       
   356 g_param_spec_get_qdata (GParamSpec *pspec,
       
   357 			GQuark      quark)
       
   358 {
       
   359   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
       
   360   
       
   361   return quark ? g_datalist_id_get_data (&pspec->qdata, quark) : NULL;
       
   362 }
       
   363 
       
   364 EXPORT_C void
       
   365 g_param_spec_set_qdata (GParamSpec *pspec,
       
   366 			GQuark      quark,
       
   367 			gpointer    data)
       
   368 {
       
   369   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
       
   370   g_return_if_fail (quark > 0);
       
   371 
       
   372   g_datalist_id_set_data (&pspec->qdata, quark, data);
       
   373 }
       
   374 
       
   375 EXPORT_C void
       
   376 g_param_spec_set_qdata_full (GParamSpec    *pspec,
       
   377 			     GQuark         quark,
       
   378 			     gpointer       data,
       
   379 			     GDestroyNotify destroy)
       
   380 {
       
   381   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
       
   382   g_return_if_fail (quark > 0);
       
   383 
       
   384   g_datalist_id_set_data_full (&pspec->qdata, quark, data, data ? destroy : (GDestroyNotify) NULL);
       
   385 }
       
   386 
       
   387 EXPORT_C gpointer
       
   388 g_param_spec_steal_qdata (GParamSpec *pspec,
       
   389 			  GQuark      quark)
       
   390 {
       
   391   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
       
   392   g_return_val_if_fail (quark > 0, NULL);
       
   393   
       
   394   return g_datalist_id_remove_no_notify (&pspec->qdata, quark);
       
   395 }
       
   396 
       
   397 EXPORT_C GParamSpec*
       
   398 g_param_spec_get_redirect_target (GParamSpec *pspec)
       
   399 {
       
   400   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
       
   401 
       
   402   if (G_IS_PARAM_SPEC_OVERRIDE (pspec))
       
   403     {
       
   404       GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
       
   405 
       
   406       return ospec->overridden;
       
   407     }
       
   408   else
       
   409     return NULL;
       
   410 }
       
   411 
       
   412 EXPORT_C void
       
   413 g_param_value_set_default (GParamSpec *pspec,
       
   414 			   GValue     *value)
       
   415 {
       
   416   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
       
   417   g_return_if_fail (G_IS_VALUE (value));
       
   418   g_return_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value));
       
   419 
       
   420   g_value_reset (value);
       
   421   G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, value);
       
   422 }
       
   423 
       
   424 EXPORT_C gboolean
       
   425 g_param_value_defaults (GParamSpec *pspec,
       
   426 			GValue     *value)
       
   427 {
       
   428   GValue dflt_value = { 0, };
       
   429   gboolean defaults;
       
   430 
       
   431   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
       
   432   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
       
   433   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE);
       
   434 
       
   435   g_value_init (&dflt_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
       
   436   G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, &dflt_value);
       
   437   defaults = G_PARAM_SPEC_GET_CLASS (pspec)->values_cmp (pspec, value, &dflt_value) == 0;
       
   438   g_value_unset (&dflt_value);
       
   439 
       
   440   return defaults;
       
   441 }
       
   442 
       
   443 EXPORT_C gboolean
       
   444 g_param_value_validate (GParamSpec *pspec,
       
   445 			GValue     *value)
       
   446 {
       
   447   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
       
   448   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
       
   449   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE);
       
   450 
       
   451   if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate)
       
   452     {
       
   453       GValue oval = *value;
       
   454 
       
   455       if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate (pspec, value) ||
       
   456 	  memcmp (&oval.data, &value->data, sizeof (oval.data)))
       
   457 	return TRUE;
       
   458     }
       
   459 
       
   460   return FALSE;
       
   461 }
       
   462 
       
   463 EXPORT_C gboolean
       
   464 g_param_value_convert (GParamSpec   *pspec,
       
   465 		       const GValue *src_value,
       
   466 		       GValue       *dest_value,
       
   467 		       gboolean	     strict_validation)
       
   468 {
       
   469   GValue tmp_value = { 0, };
       
   470 
       
   471   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
       
   472   g_return_val_if_fail (G_IS_VALUE (src_value), FALSE);
       
   473   g_return_val_if_fail (G_IS_VALUE (dest_value), FALSE);
       
   474   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, dest_value), FALSE);
       
   475 
       
   476   /* better leave dest_value untouched when returning FALSE */
       
   477 
       
   478   g_value_init (&tmp_value, G_VALUE_TYPE (dest_value));
       
   479   if (g_value_transform (src_value, &tmp_value) &&
       
   480       (!g_param_value_validate (pspec, &tmp_value) || !strict_validation))
       
   481     {
       
   482       g_value_unset (dest_value);
       
   483       
       
   484       /* values are relocatable */
       
   485       memcpy (dest_value, &tmp_value, sizeof (tmp_value));
       
   486       
       
   487       return TRUE;
       
   488     }
       
   489   else
       
   490     {
       
   491       g_value_unset (&tmp_value);
       
   492       
       
   493       return FALSE;
       
   494     }
       
   495 }
       
   496 
       
   497 EXPORT_C gint
       
   498 g_param_values_cmp (GParamSpec   *pspec,
       
   499 		    const GValue *value1,
       
   500 		    const GValue *value2)
       
   501 {
       
   502   gint cmp;
       
   503 
       
   504   /* param_values_cmp() effectively does: value1 - value2
       
   505    * so the return values are:
       
   506    * -1)  value1 < value2
       
   507    *  0)  value1 == value2
       
   508    *  1)  value1 > value2
       
   509    */
       
   510   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), 0);
       
   511   g_return_val_if_fail (G_IS_VALUE (value1), 0);
       
   512   g_return_val_if_fail (G_IS_VALUE (value2), 0);
       
   513   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value1), 0);
       
   514   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value2), 0);
       
   515 
       
   516   cmp = G_PARAM_SPEC_GET_CLASS (pspec)->values_cmp (pspec, value1, value2);
       
   517 
       
   518   return CLAMP (cmp, -1, 1);
       
   519 }
       
   520 
       
   521 static void
       
   522 value_param_init (GValue *value)
       
   523 {
       
   524   value->data[0].v_pointer = NULL;
       
   525 }
       
   526 
       
   527 static void
       
   528 value_param_free_value (GValue *value)
       
   529 {
       
   530   if (value->data[0].v_pointer)
       
   531     g_param_spec_unref (value->data[0].v_pointer);
       
   532 }
       
   533 
       
   534 static void
       
   535 value_param_copy_value (const GValue *src_value,
       
   536 			GValue       *dest_value)
       
   537 {
       
   538   if (src_value->data[0].v_pointer)
       
   539     dest_value->data[0].v_pointer = g_param_spec_ref (src_value->data[0].v_pointer);
       
   540   else
       
   541     dest_value->data[0].v_pointer = NULL;
       
   542 }
       
   543 
       
   544 static void
       
   545 value_param_transform_value (const GValue *src_value,
       
   546 			     GValue       *dest_value)
       
   547 {
       
   548   if (src_value->data[0].v_pointer &&
       
   549       g_type_is_a (G_PARAM_SPEC_TYPE (dest_value->data[0].v_pointer), G_VALUE_TYPE (dest_value)))
       
   550     dest_value->data[0].v_pointer = g_param_spec_ref (src_value->data[0].v_pointer);
       
   551   else
       
   552     dest_value->data[0].v_pointer = NULL;
       
   553 }
       
   554 
       
   555 static gpointer
       
   556 value_param_peek_pointer (const GValue *value)
       
   557 {
       
   558   return value->data[0].v_pointer;
       
   559 }
       
   560 
       
   561 static gchar*
       
   562 value_param_collect_value (GValue      *value,
       
   563 			   guint        n_collect_values,
       
   564 			   GTypeCValue *collect_values,
       
   565 			   guint        collect_flags)
       
   566 {
       
   567   if (collect_values[0].v_pointer)
       
   568     {
       
   569       GParamSpec *param = collect_values[0].v_pointer;
       
   570 
       
   571       if (param->g_type_instance.g_class == NULL)
       
   572 	return g_strconcat ("invalid unclassed param spec pointer for value type `",
       
   573 			    G_VALUE_TYPE_NAME (value),
       
   574 			    "'",
       
   575 			    NULL);
       
   576       else if (!g_value_type_compatible (G_PARAM_SPEC_TYPE (param), G_VALUE_TYPE (value)))
       
   577 	return g_strconcat ("invalid param spec type `",
       
   578 			    G_PARAM_SPEC_TYPE_NAME (param),
       
   579 			    "' for value type `",
       
   580 			    G_VALUE_TYPE_NAME (value),
       
   581 			    "'",
       
   582 			    NULL);
       
   583       value->data[0].v_pointer = g_param_spec_ref (param);
       
   584     }
       
   585   else
       
   586     value->data[0].v_pointer = NULL;
       
   587 
       
   588   return NULL;
       
   589 }
       
   590 
       
   591 static gchar*
       
   592 value_param_lcopy_value (const GValue *value,
       
   593 			 guint         n_collect_values,
       
   594 			 GTypeCValue  *collect_values,
       
   595 			 guint         collect_flags)
       
   596 {
       
   597   GParamSpec **param_p = collect_values[0].v_pointer;
       
   598 
       
   599   if (!param_p)
       
   600     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
       
   601 
       
   602   if (!value->data[0].v_pointer)
       
   603     *param_p = NULL;
       
   604   else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
       
   605     *param_p = value->data[0].v_pointer;
       
   606   else
       
   607     *param_p = g_param_spec_ref (value->data[0].v_pointer);
       
   608 
       
   609   return NULL;
       
   610 }
       
   611 
       
   612 
       
   613 /* --- param spec pool --- */
       
   614 struct _GParamSpecPool
       
   615 {
       
   616   GStaticMutex smutex;
       
   617   gboolean     type_prefixing;
       
   618   GHashTable  *hash_table;
       
   619 };
       
   620 
       
   621 static guint
       
   622 param_spec_pool_hash (gconstpointer key_spec)
       
   623 {
       
   624   const GParamSpec *key = key_spec;
       
   625   const gchar *p;
       
   626   guint h = key->owner_type;
       
   627 
       
   628   for (p = key->name; *p; p++)
       
   629     h = (h << 5) - h + *p;
       
   630 
       
   631   return h;
       
   632 }
       
   633 
       
   634 static gboolean
       
   635 param_spec_pool_equals (gconstpointer key_spec_1,
       
   636 			gconstpointer key_spec_2)
       
   637 {
       
   638   const GParamSpec *key1 = key_spec_1;
       
   639   const GParamSpec *key2 = key_spec_2;
       
   640 
       
   641   return (key1->owner_type == key2->owner_type &&
       
   642 	  strcmp (key1->name, key2->name) == 0);
       
   643 }
       
   644 
       
   645 #if EMULATOR
       
   646 
       
   647 PLS(init_smutex,g_param_spec_pool_new ,GStaticMutex)
       
   648 #define init_smutex (*FUNCTION_NAME(init_smutex,g_param_spec_pool_new )())
       
   649 
       
   650 #endif /* EMULATOR */
       
   651 
       
   652 
       
   653 EXPORT_C GParamSpecPool*
       
   654 g_param_spec_pool_new (gboolean type_prefixing)
       
   655 {
       
   656   #if !(EMULATOR)
       
   657   static GStaticMutex init_smutex = G_STATIC_MUTEX_INIT;
       
   658   #endif /* EMULATOR */
       
   659   GParamSpecPool *pool = g_new (GParamSpecPool, 1);
       
   660 
       
   661   memcpy (&pool->smutex, &init_smutex, sizeof (init_smutex));
       
   662   pool->type_prefixing = type_prefixing != FALSE;
       
   663   pool->hash_table = g_hash_table_new (param_spec_pool_hash, param_spec_pool_equals);
       
   664 
       
   665   return pool;
       
   666 }
       
   667 
       
   668 #if EMULATOR
       
   669 #undef init_smutex 
       
   670 #endif /* EMULATOR */
       
   671 
       
   672 EXPORT_C void
       
   673 g_param_spec_pool_insert (GParamSpecPool *pool,
       
   674 			  GParamSpec     *pspec,
       
   675 			  GType           owner_type)
       
   676 {
       
   677   gchar *p;
       
   678   
       
   679   if (pool && pspec && owner_type > 0 && pspec->owner_type == 0)
       
   680     {
       
   681       G_SLOCK (&pool->smutex);
       
   682       for (p = pspec->name; *p; p++)
       
   683 	{
       
   684 	  if (!strchr (G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-_", *p))
       
   685 	    {
       
   686 	      g_warning (G_STRLOC ": pspec name \"%s\" contains invalid characters", pspec->name);
       
   687 	      G_SUNLOCK (&pool->smutex);
       
   688 	      return;
       
   689 	    }
       
   690 	}
       
   691       
       
   692       pspec->owner_type = owner_type;
       
   693       g_param_spec_ref (pspec);
       
   694       g_hash_table_insert (pool->hash_table, pspec, pspec);
       
   695       G_SUNLOCK (&pool->smutex);
       
   696     }
       
   697   else
       
   698     {
       
   699       g_return_if_fail (pool != NULL);
       
   700       g_return_if_fail (pspec);
       
   701       g_return_if_fail (owner_type > 0);
       
   702       g_return_if_fail (pspec->owner_type == 0);
       
   703     }
       
   704 }
       
   705 
       
   706 EXPORT_C void
       
   707 g_param_spec_pool_remove (GParamSpecPool *pool,
       
   708 			  GParamSpec     *pspec)
       
   709 {
       
   710   if (pool && pspec)
       
   711     {
       
   712       G_SLOCK (&pool->smutex);
       
   713       if (g_hash_table_remove (pool->hash_table, pspec))
       
   714 	g_param_spec_unref (pspec);
       
   715       else
       
   716 	g_warning (G_STRLOC ": attempt to remove unknown pspec `%s' from pool", pspec->name);
       
   717       G_SUNLOCK (&pool->smutex);
       
   718     }
       
   719   else
       
   720     {
       
   721       g_return_if_fail (pool != NULL);
       
   722       g_return_if_fail (pspec);
       
   723     }
       
   724 }
       
   725 
       
   726 static inline GParamSpec*
       
   727 param_spec_ht_lookup (GHashTable  *hash_table,
       
   728 		      const gchar *param_name,
       
   729 		      GType        owner_type,
       
   730 		      gboolean     walk_ancestors)
       
   731 {
       
   732   GParamSpec key, *pspec;
       
   733 
       
   734   key.owner_type = owner_type;
       
   735   key.name = (gchar*) param_name;
       
   736   if (walk_ancestors)
       
   737     do
       
   738       {
       
   739 	pspec = g_hash_table_lookup (hash_table, &key);
       
   740 	if (pspec)
       
   741 	  return pspec;
       
   742 	key.owner_type = g_type_parent (key.owner_type);
       
   743       }
       
   744     while (key.owner_type);
       
   745   else
       
   746     pspec = g_hash_table_lookup (hash_table, &key);
       
   747 
       
   748   if (!pspec && !is_canonical (param_name))
       
   749     {
       
   750       /* try canonicalized form */
       
   751       key.name = g_strdup (param_name);
       
   752       key.owner_type = owner_type;
       
   753       
       
   754       canonicalize_key (key.name);
       
   755       if (walk_ancestors)
       
   756 	do
       
   757 	  {
       
   758 	    pspec = g_hash_table_lookup (hash_table, &key);
       
   759 	    if (pspec)
       
   760 	      {
       
   761 		g_free (key.name);
       
   762 		return pspec;
       
   763 	      }
       
   764 	    key.owner_type = g_type_parent (key.owner_type);
       
   765 	  }
       
   766 	while (key.owner_type);
       
   767       else
       
   768 	pspec = g_hash_table_lookup (hash_table, &key);
       
   769       g_free (key.name);
       
   770     }
       
   771 
       
   772   return pspec;
       
   773 }
       
   774 
       
   775 EXPORT_C GParamSpec*
       
   776 g_param_spec_pool_lookup (GParamSpecPool *pool,
       
   777 			  const gchar    *param_name,
       
   778 			  GType           owner_type,
       
   779 			  gboolean        walk_ancestors)
       
   780 {
       
   781   GParamSpec *pspec;
       
   782   gchar *delim;
       
   783 
       
   784   if (!pool || !param_name)
       
   785     {
       
   786       g_return_val_if_fail (pool != NULL, NULL);
       
   787       g_return_val_if_fail (param_name != NULL, NULL);
       
   788     }
       
   789 
       
   790   G_SLOCK (&pool->smutex);
       
   791 
       
   792   delim = pool->type_prefixing ? strchr (param_name, ':') : NULL;
       
   793 
       
   794   /* try quick and away, i.e. without prefix */
       
   795   if (!delim)
       
   796     {
       
   797       pspec = param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
       
   798       G_SUNLOCK (&pool->smutex);
       
   799 
       
   800       return pspec;
       
   801     }
       
   802 
       
   803   /* strip type prefix */
       
   804   if (pool->type_prefixing && delim[1] == ':')
       
   805     {
       
   806       guint l = delim - param_name;
       
   807       gchar stack_buffer[32], *buffer = l < 32 ? stack_buffer : g_new (gchar, l + 1);
       
   808       GType type;
       
   809       
       
   810       strncpy (buffer, param_name, delim - param_name);
       
   811       buffer[l] = 0;
       
   812       type = g_type_from_name (buffer);
       
   813       if (l >= 32)
       
   814 	g_free (buffer);
       
   815       if (type)		/* type==0 isn't a valid type pefix */
       
   816 	{
       
   817 	  /* sanity check, these cases don't make a whole lot of sense */
       
   818 	  if ((!walk_ancestors && type != owner_type) || !g_type_is_a (owner_type, type))
       
   819 	    {
       
   820 	      G_SUNLOCK (&pool->smutex);
       
   821 
       
   822 	      return NULL;
       
   823 	    }
       
   824 	  owner_type = type;
       
   825 	  param_name += l + 2;
       
   826 	  pspec = param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
       
   827 	  G_SUNLOCK (&pool->smutex);
       
   828 
       
   829 	  return pspec;
       
   830 	}
       
   831     }
       
   832   /* malformed param_name */
       
   833 
       
   834   G_SUNLOCK (&pool->smutex);
       
   835 
       
   836   return NULL;
       
   837 }
       
   838 
       
   839 static void
       
   840 pool_list (gpointer key,
       
   841 	   gpointer value,
       
   842 	   gpointer user_data)
       
   843 {
       
   844   GParamSpec *pspec = value;
       
   845   gpointer *data = user_data;
       
   846   GType owner_type = (GType) data[1];
       
   847 
       
   848   if (owner_type == pspec->owner_type)
       
   849     data[0] = g_list_prepend (data[0], pspec);
       
   850 }
       
   851 
       
   852 EXPORT_C GList*
       
   853 g_param_spec_pool_list_owned (GParamSpecPool *pool,
       
   854 			      GType           owner_type)
       
   855 {
       
   856   gpointer data[2];
       
   857 
       
   858   g_return_val_if_fail (pool != NULL, NULL);
       
   859   g_return_val_if_fail (owner_type > 0, NULL);
       
   860   
       
   861   G_SLOCK (&pool->smutex);
       
   862   data[0] = NULL;
       
   863   data[1] = (gpointer) owner_type;
       
   864   g_hash_table_foreach (pool->hash_table, pool_list, &data);
       
   865   G_SUNLOCK (&pool->smutex);
       
   866 
       
   867   return data[0];
       
   868 }
       
   869 
       
   870 static gint
       
   871 pspec_compare_id (gconstpointer a,
       
   872 		  gconstpointer b)
       
   873 {
       
   874   const GParamSpec *pspec1 = a, *pspec2 = b;
       
   875 
       
   876   return pspec1->param_id < pspec2->param_id ? -1 : pspec1->param_id > pspec2->param_id;
       
   877 }
       
   878 
       
   879 static inline GSList*
       
   880 pspec_list_remove_overridden_and_redirected (GSList     *plist,
       
   881 					     GHashTable *ht,
       
   882 					     GType       owner_type,
       
   883 					     guint      *n_p)
       
   884 {
       
   885   GSList *rlist = NULL;
       
   886 
       
   887   while (plist)
       
   888     {
       
   889       GSList *tmp = plist->next;
       
   890       GParamSpec *pspec = plist->data;
       
   891       GParamSpec *found;
       
   892       gboolean remove = FALSE;
       
   893 
       
   894       /* Remove paramspecs that are redirected, and also paramspecs
       
   895        * that have are overridden by non-redirected properties.
       
   896        * The idea is to get the single paramspec for each name that
       
   897        * best corresponds to what the application sees.
       
   898        */
       
   899       if (g_param_spec_get_redirect_target (pspec))
       
   900 	remove = TRUE;
       
   901       else
       
   902 	{
       
   903 	  found = param_spec_ht_lookup (ht, pspec->name, owner_type, TRUE);
       
   904 	  if (found != pspec)
       
   905 	    {
       
   906 	      GParamSpec *redirect = g_param_spec_get_redirect_target (found);
       
   907 	      if (redirect != pspec)
       
   908 		remove = TRUE;
       
   909 	    }
       
   910 	}
       
   911 
       
   912       if (remove)
       
   913 	{
       
   914 	  g_slist_free_1 (plist);
       
   915 	}
       
   916       else
       
   917 	{
       
   918 	  plist->next = rlist;
       
   919 	  rlist = plist;
       
   920 	  *n_p += 1;
       
   921 	}
       
   922       plist = tmp;
       
   923     }
       
   924   return rlist;
       
   925 }
       
   926 
       
   927 static void
       
   928 pool_depth_list (gpointer key,
       
   929 		 gpointer value,
       
   930 		 gpointer user_data)
       
   931 {
       
   932   GParamSpec *pspec = value;
       
   933   gpointer *data = user_data;
       
   934   GSList **slists = data[0];
       
   935   GType owner_type = (GType) data[1];
       
   936 
       
   937   if (g_type_is_a (owner_type, pspec->owner_type))
       
   938     {
       
   939       if (G_TYPE_IS_INTERFACE (pspec->owner_type))
       
   940 	{
       
   941 	  slists[0] = g_slist_prepend (slists[0], pspec);
       
   942 	}
       
   943       else
       
   944 	{
       
   945 	  guint d = g_type_depth (pspec->owner_type);
       
   946 
       
   947 	  slists[d - 1] = g_slist_prepend (slists[d - 1], pspec);
       
   948 	}
       
   949     }
       
   950 }
       
   951 
       
   952 /* We handle interfaces specially since we don't want to
       
   953  * count interface prerequsites like normal inheritance;
       
   954  * the property comes from the direct inheritance from
       
   955  * the prerequisite class, not from the interface that
       
   956  * prerequires it.
       
   957  * 
       
   958  * also 'depth' isn't a meaningful concept for interface
       
   959  * prerequites.
       
   960  */
       
   961 static void
       
   962 pool_depth_list_for_interface (gpointer key,
       
   963 			       gpointer value,
       
   964 			       gpointer user_data)
       
   965 {
       
   966   GParamSpec *pspec = value;
       
   967   gpointer *data = user_data;
       
   968   GSList **slists = data[0];
       
   969   GType owner_type = (GType) data[1];
       
   970 
       
   971   if (pspec->owner_type == owner_type)
       
   972     slists[0] = g_slist_prepend (slists[0], pspec);
       
   973 }
       
   974 
       
   975 EXPORT_C GParamSpec** /* free result */
       
   976 g_param_spec_pool_list (GParamSpecPool *pool,
       
   977 			GType           owner_type,
       
   978 			guint          *n_pspecs_p)
       
   979 {
       
   980   GParamSpec **pspecs, **p;
       
   981   GSList **slists, *node;
       
   982   gpointer data[2];
       
   983   guint d, i;
       
   984 
       
   985   g_return_val_if_fail (pool != NULL, NULL);
       
   986   g_return_val_if_fail (owner_type > 0, NULL);
       
   987   g_return_val_if_fail (n_pspecs_p != NULL, NULL);
       
   988   
       
   989   G_SLOCK (&pool->smutex);
       
   990   *n_pspecs_p = 0;
       
   991   d = g_type_depth (owner_type);
       
   992   slists = g_new0 (GSList*, d);
       
   993   data[0] = slists;
       
   994   data[1] = (gpointer) owner_type;
       
   995 
       
   996   g_hash_table_foreach (pool->hash_table,
       
   997 			G_TYPE_IS_INTERFACE (owner_type) ?
       
   998 			   pool_depth_list_for_interface :
       
   999 			   pool_depth_list,
       
  1000 			&data);
       
  1001   
       
  1002   for (i = 0; i < d; i++)
       
  1003     slists[i] = pspec_list_remove_overridden_and_redirected (slists[i], pool->hash_table, owner_type, n_pspecs_p);
       
  1004   pspecs = g_new (GParamSpec*, *n_pspecs_p + 1);
       
  1005   p = pspecs;
       
  1006   for (i = 0; i < d; i++)
       
  1007     {
       
  1008       slists[i] = g_slist_sort (slists[i], pspec_compare_id);
       
  1009       for (node = slists[i]; node; node = node->next)
       
  1010 	*p++ = node->data;
       
  1011       g_slist_free (slists[i]);
       
  1012     }
       
  1013   *p++ = NULL;
       
  1014   g_free (slists);
       
  1015   G_SUNLOCK (&pool->smutex);
       
  1016 
       
  1017   return pspecs;
       
  1018 }
       
  1019 
       
  1020 
       
  1021 /* --- auxillary functions --- */
       
  1022 typedef struct
       
  1023 {
       
  1024   /* class portion */
       
  1025   GType           value_type;
       
  1026   void          (*finalize)             (GParamSpec   *pspec);
       
  1027   void          (*value_set_default)    (GParamSpec   *pspec,
       
  1028 					 GValue       *value);
       
  1029   gboolean      (*value_validate)       (GParamSpec   *pspec,
       
  1030 					 GValue       *value);
       
  1031   gint          (*values_cmp)           (GParamSpec   *pspec,
       
  1032 					 const GValue *value1,
       
  1033 					 const GValue *value2);
       
  1034 } ParamSpecClassInfo;
       
  1035 
       
  1036 static void
       
  1037 param_spec_generic_class_init (gpointer g_class,
       
  1038 			       gpointer class_data)
       
  1039 {
       
  1040   GParamSpecClass *class = g_class;
       
  1041   ParamSpecClassInfo *info = class_data;
       
  1042 
       
  1043   class->value_type = info->value_type;
       
  1044   if (info->finalize)
       
  1045     class->finalize = info->finalize;			/* optional */
       
  1046   class->value_set_default = info->value_set_default;
       
  1047   if (info->value_validate)
       
  1048     class->value_validate = info->value_validate;	/* optional */
       
  1049   class->values_cmp = info->values_cmp;
       
  1050   g_free (class_data);
       
  1051 }
       
  1052 
       
  1053 static void
       
  1054 default_value_set_default (GParamSpec *pspec,
       
  1055 			   GValue     *value)
       
  1056 {
       
  1057   /* value is already zero initialized */
       
  1058 }
       
  1059 
       
  1060 static gint
       
  1061 default_values_cmp (GParamSpec   *pspec,
       
  1062 		    const GValue *value1,
       
  1063 		    const GValue *value2)
       
  1064 {
       
  1065   return memcmp (&value1->data, &value2->data, sizeof (value1->data));
       
  1066 }
       
  1067 
       
  1068 EXPORT_C GType
       
  1069 g_param_type_register_static (const gchar              *name,
       
  1070 			      const GParamSpecTypeInfo *pspec_info)
       
  1071 {
       
  1072   GTypeInfo info = {
       
  1073     sizeof (GParamSpecClass),      /* class_size */
       
  1074     NULL,                          /* base_init */
       
  1075     NULL,                          /* base_destroy */
       
  1076     param_spec_generic_class_init, /* class_init */
       
  1077     NULL,                          /* class_destroy */
       
  1078     NULL,                          /* class_data */
       
  1079     0,                             /* instance_size */
       
  1080     16,                            /* n_preallocs */
       
  1081     NULL,                          /* instance_init */
       
  1082   };
       
  1083   ParamSpecClassInfo *cinfo;
       
  1084 
       
  1085   g_return_val_if_fail (name != NULL, 0);
       
  1086   g_return_val_if_fail (pspec_info != NULL, 0);
       
  1087   g_return_val_if_fail (g_type_from_name (name) == 0, 0);
       
  1088   g_return_val_if_fail (pspec_info->instance_size >= sizeof (GParamSpec), 0);
       
  1089   g_return_val_if_fail (g_type_name (pspec_info->value_type) != NULL, 0);
       
  1090   /* default: g_return_val_if_fail (pspec_info->value_set_default != NULL, 0); */
       
  1091   /* optional: g_return_val_if_fail (pspec_info->value_validate != NULL, 0); */
       
  1092   /* default: g_return_val_if_fail (pspec_info->values_cmp != NULL, 0); */
       
  1093 
       
  1094   info.instance_size = pspec_info->instance_size;
       
  1095   info.n_preallocs = pspec_info->n_preallocs;
       
  1096   info.instance_init = (GInstanceInitFunc) pspec_info->instance_init;
       
  1097   cinfo = g_new (ParamSpecClassInfo, 1);
       
  1098   cinfo->value_type = pspec_info->value_type;
       
  1099   cinfo->finalize = pspec_info->finalize;
       
  1100   cinfo->value_set_default = pspec_info->value_set_default ? pspec_info->value_set_default : default_value_set_default;
       
  1101   cinfo->value_validate = pspec_info->value_validate;
       
  1102   cinfo->values_cmp = pspec_info->values_cmp ? pspec_info->values_cmp : default_values_cmp;
       
  1103   info.class_data = cinfo;
       
  1104 
       
  1105   return g_type_register_static (G_TYPE_PARAM, name, &info, 0);
       
  1106 }
       
  1107 
       
  1108 EXPORT_C void
       
  1109 g_value_set_param (GValue     *value,
       
  1110 		   GParamSpec *param)
       
  1111 {
       
  1112   g_return_if_fail (G_VALUE_HOLDS_PARAM (value));
       
  1113   if (param)
       
  1114     g_return_if_fail (G_IS_PARAM_SPEC (param));
       
  1115 
       
  1116   if (value->data[0].v_pointer)
       
  1117     g_param_spec_unref (value->data[0].v_pointer);
       
  1118   value->data[0].v_pointer = param;
       
  1119   if (value->data[0].v_pointer)
       
  1120     g_param_spec_ref (value->data[0].v_pointer);
       
  1121 }
       
  1122 
       
  1123 EXPORT_C void
       
  1124 g_value_set_param_take_ownership (GValue     *value,
       
  1125 				  GParamSpec *param)
       
  1126 {
       
  1127   g_value_take_param (value, param);
       
  1128 }
       
  1129 
       
  1130 EXPORT_C void
       
  1131 g_value_take_param (GValue     *value,
       
  1132 		    GParamSpec *param)
       
  1133 {
       
  1134   g_return_if_fail (G_VALUE_HOLDS_PARAM (value));
       
  1135   if (param)
       
  1136     g_return_if_fail (G_IS_PARAM_SPEC (param));
       
  1137 
       
  1138   if (value->data[0].v_pointer)
       
  1139     g_param_spec_unref (value->data[0].v_pointer);
       
  1140   value->data[0].v_pointer = param; /* we take over the reference count */
       
  1141 }
       
  1142 
       
  1143 EXPORT_C GParamSpec*
       
  1144 g_value_get_param (const GValue *value)
       
  1145 {
       
  1146   g_return_val_if_fail (G_VALUE_HOLDS_PARAM (value), NULL);
       
  1147 
       
  1148   return value->data[0].v_pointer;
       
  1149 }
       
  1150 
       
  1151 EXPORT_C GParamSpec*
       
  1152 g_value_dup_param (const GValue *value)
       
  1153 {
       
  1154   g_return_val_if_fail (G_VALUE_HOLDS_PARAM (value), NULL);
       
  1155 
       
  1156   return value->data[0].v_pointer ? g_param_spec_ref (value->data[0].v_pointer) : NULL;
       
  1157 }
       
  1158 
       
  1159 #define __G_PARAM_C__
       
  1160 #include "gobjectaliasdef.c"