📄 gparam.c
字号:
/* GObject - GLib Type, Object, Parameter and Signal Library * Copyright (C) 1997-1999, 2000-2001 Tim Janik and Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. *//* * MT safe */#include "gparam.h"#include "gvaluecollector.h"#include <string.h>/* --- defines --- */#define G_PARAM_USER_MASK (~0 << G_PARAM_USER_SHIFT)#define PSPEC_APPLIES_TO_VALUE(pspec, value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_PARAM_SPEC_VALUE_TYPE (pspec)))#define G_SLOCK(mutex) g_static_mutex_lock (mutex)#define G_SUNLOCK(mutex) g_static_mutex_unlock (mutex)/* --- prototypes --- */static void g_param_spec_class_base_init (GParamSpecClass *class);static void g_param_spec_class_base_finalize (GParamSpecClass *class);static void g_param_spec_class_init (GParamSpecClass *class, gpointer class_data);static void g_param_spec_init (GParamSpec *pspec, GParamSpecClass *class);static void g_param_spec_finalize (GParamSpec *pspec);static void value_param_init (GValue *value);static void value_param_free_value (GValue *value);static void value_param_copy_value (const GValue *src_value, GValue *dest_value);static void value_param_transform_value (const GValue *src_value, GValue *dest_value);static gpointer value_param_peek_pointer (const GValue *value);static gchar* value_param_collect_value (GValue *value, guint n_collect_values, GTypeCValue *collect_values, guint collect_flags);static gchar* value_param_lcopy_value (const GValue *value, guint n_collect_values, GTypeCValue *collect_values, guint collect_flags);/* --- variables --- */static GQuark quark_floating = 0;G_LOCK_DEFINE_STATIC (pspec_ref_count);/* --- functions --- */voidg_param_type_init (void) /* sync with gtype.c */{ static const GTypeFundamentalInfo finfo = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE), }; static const GTypeValueTable param_value_table = { value_param_init, /* value_init */ value_param_free_value, /* value_free */ value_param_copy_value, /* value_copy */ value_param_peek_pointer, /* value_peek_pointer */ "p", /* collect_format */ value_param_collect_value, /* collect_value */ "p", /* lcopy_format */ value_param_lcopy_value, /* lcopy_value */ }; static const GTypeInfo param_spec_info = { sizeof (GParamSpecClass), (GBaseInitFunc) g_param_spec_class_base_init, (GBaseFinalizeFunc) g_param_spec_class_base_finalize, (GClassInitFunc) g_param_spec_class_init, (GClassFinalizeFunc) NULL, NULL, /* class_data */ sizeof (GParamSpec), 0, /* n_preallocs */ (GInstanceInitFunc) g_param_spec_init, ¶m_value_table, }; GType type; type = g_type_register_fundamental (G_TYPE_PARAM, "GParam", ¶m_spec_info, &finfo, G_TYPE_FLAG_ABSTRACT); g_assert (type == G_TYPE_PARAM); g_value_register_transform_func (G_TYPE_PARAM, G_TYPE_PARAM, value_param_transform_value);}static voidg_param_spec_class_base_init (GParamSpecClass *class){}static voidg_param_spec_class_base_finalize (GParamSpecClass *class){}static voidg_param_spec_class_init (GParamSpecClass *class, gpointer class_data){ quark_floating = g_quark_from_static_string ("GParamSpec-floating"); class->value_type = G_TYPE_NONE; class->finalize = g_param_spec_finalize; class->value_set_default = NULL; class->value_validate = NULL; class->values_cmp = NULL;}static voidg_param_spec_init (GParamSpec *pspec, GParamSpecClass *class){ pspec->name = NULL; pspec->_nick = NULL; pspec->_blurb = NULL; pspec->flags = 0; pspec->value_type = class->value_type; pspec->owner_type = 0; pspec->qdata = NULL; pspec->ref_count = 1; pspec->param_id = 0; g_datalist_id_set_data (&pspec->qdata, quark_floating, GUINT_TO_POINTER (TRUE));}static voidg_param_spec_finalize (GParamSpec *pspec){ g_datalist_clear (&pspec->qdata); g_free (pspec->name); g_free (pspec->_nick); g_free (pspec->_blurb); g_type_free_instance ((GTypeInstance*) pspec);}GParamSpec*g_param_spec_ref (GParamSpec *pspec){ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL); G_LOCK (pspec_ref_count); if (pspec->ref_count > 0) { pspec->ref_count += 1; G_UNLOCK (pspec_ref_count); } else { G_UNLOCK (pspec_ref_count); g_return_val_if_fail (pspec->ref_count > 0, NULL); } return pspec;}voidg_param_spec_unref (GParamSpec *pspec){ g_return_if_fail (G_IS_PARAM_SPEC (pspec)); G_LOCK (pspec_ref_count); if (pspec->ref_count > 0) { gboolean need_finalize; /* sync with _sink */ pspec->ref_count -= 1; need_finalize = pspec->ref_count == 0; G_UNLOCK (pspec_ref_count); if (need_finalize) G_PARAM_SPEC_GET_CLASS (pspec)->finalize (pspec); } else { G_UNLOCK (pspec_ref_count); g_return_if_fail (pspec->ref_count > 0); }}voidg_param_spec_sink (GParamSpec *pspec){ g_return_if_fail (G_IS_PARAM_SPEC (pspec)); G_LOCK (pspec_ref_count); if (pspec->ref_count > 0) { if (g_datalist_id_remove_no_notify (&pspec->qdata, quark_floating)) { /* sync with _unref */ if (pspec->ref_count > 1) pspec->ref_count -= 1; else { G_UNLOCK (pspec_ref_count); g_param_spec_unref (pspec); return; } } G_UNLOCK (pspec_ref_count); } else { G_UNLOCK (pspec_ref_count); g_return_if_fail (pspec->ref_count > 0); }}G_CONST_RETURN gchar*g_param_spec_get_name (GParamSpec *pspec){ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL); return pspec->name;}G_CONST_RETURN gchar*g_param_spec_get_nick (GParamSpec *pspec){ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL); return pspec->_nick ? pspec->_nick : pspec->name;}G_CONST_RETURN gchar*g_param_spec_get_blurb (GParamSpec *pspec){ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL); return pspec->_blurb;}static voidcanonalize_key (gchar *key){ gchar *p; for (p = key; *p != 0; p++) { gchar c = *p; if (c != '-' && (c < '0' || c > '9') && (c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) *p = '-'; }}gpointerg_param_spec_internal (GType param_type, const gchar *name, const gchar *nick, const gchar *blurb, GParamFlags flags){ GParamSpec *pspec; g_return_val_if_fail (G_TYPE_IS_PARAM (param_type) && param_type != G_TYPE_PARAM, NULL); g_return_val_if_fail (name != NULL, NULL); g_return_val_if_fail ((name[0] >= 'A' && name[0] <= 'Z') || (name[0] >= 'a' && name[0] <= 'z'), NULL); pspec = (gpointer) g_type_create_instance (param_type); pspec->name = g_strdup (name); canonalize_key (pspec->name); pspec->_nick = g_strdup (nick); pspec->_blurb = g_strdup (blurb); pspec->flags = (flags & G_PARAM_USER_MASK) | (flags & G_PARAM_MASK); return pspec;}gpointerg_param_spec_get_qdata (GParamSpec *pspec, GQuark quark){ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL); return quark ? g_datalist_id_get_data (&pspec->qdata, quark) : NULL;}voidg_param_spec_set_qdata (GParamSpec *pspec, GQuark quark, gpointer data){ g_return_if_fail (G_IS_PARAM_SPEC (pspec)); g_return_if_fail (quark > 0); g_datalist_id_set_data (&pspec->qdata, quark, data);}voidg_param_spec_set_qdata_full (GParamSpec *pspec, GQuark quark, gpointer data, GDestroyNotify destroy){ g_return_if_fail (G_IS_PARAM_SPEC (pspec)); g_return_if_fail (quark > 0); g_datalist_id_set_data_full (&pspec->qdata, quark, data, data ? destroy : (GDestroyNotify) NULL);}gpointerg_param_spec_steal_qdata (GParamSpec *pspec, GQuark quark){ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL); g_return_val_if_fail (quark > 0, NULL); return g_datalist_id_remove_no_notify (&pspec->qdata, quark);}voidg_param_value_set_default (GParamSpec *pspec, GValue *value){ g_return_if_fail (G_IS_PARAM_SPEC (pspec)); g_return_if_fail (G_IS_VALUE (value)); g_return_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value)); g_value_reset (value); G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, value);}gbooleang_param_value_defaults (GParamSpec *pspec, GValue *value){ GValue dflt_value = { 0, }; gboolean defaults; g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE); g_return_val_if_fail (G_IS_VALUE (value), FALSE); g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE); g_value_init (&dflt_value, G_PARAM_SPEC_VALUE_TYPE (pspec)); G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, &dflt_value); defaults = G_PARAM_SPEC_GET_CLASS (pspec)->values_cmp (pspec, value, &dflt_value) == 0; g_value_unset (&dflt_value); return defaults;}gbooleang_param_value_validate (GParamSpec *pspec, GValue *value){ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE); g_return_val_if_fail (G_IS_VALUE (value), FALSE); g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE); if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate) { GValue oval = *value; if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate (pspec, value) || memcmp (&oval.data, &value->data, sizeof (oval.data))) return TRUE; } return FALSE;}gbooleang_param_value_convert (GParamSpec *pspec, const GValue *src_value, GValue *dest_value, gboolean strict_validation){ GValue tmp_value = { 0, }; g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE); g_return_val_if_fail (G_IS_VALUE (src_value), FALSE); g_return_val_if_fail (G_IS_VALUE (dest_value), FALSE); g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, dest_value), FALSE); /* better leave dest_value untouched when returning FALSE */ g_value_init (&tmp_value, G_VALUE_TYPE (dest_value)); if (g_value_transform (src_value, &tmp_value) && (!g_param_value_validate (pspec, &tmp_value) || !strict_validation)) { g_value_unset (dest_value); /* values are relocatable */ memcpy (dest_value, &tmp_value, sizeof (tmp_value)); return TRUE; } else { g_value_unset (&tmp_value); return FALSE; }}gintg_param_values_cmp (GParamSpec *pspec, const GValue *value1, const GValue *value2){ gint cmp; /* param_values_cmp() effectively does: value1 - value2 * so the return values are: * -1) value1 < value2 * 0) value1 == value2 * 1) value1 > value2 */ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), 0); g_return_val_if_fail (G_IS_VALUE (value1), 0); g_return_val_if_fail (G_IS_VALUE (value2), 0); g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value1), 0); g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value2), 0); cmp = G_PARAM_SPEC_GET_CLASS (pspec)->values_cmp (pspec, value1, value2); return CLAMP (cmp, -1, 1);}static voidvalue_param_init (GValue *value){ value->data[0].v_pointer = NULL;}static voidvalue_param_free_value (GValue *value){ if (value->data[0].v_pointer) g_param_spec_unref (value->data[0].v_pointer);}static voidvalue_param_copy_value (const GValue *src_value, GValue *dest_value){ if (src_value->data[0].v_pointer) dest_value->data[0].v_pointer = g_param_spec_ref (src_value->data[0].v_pointer); else dest_value->data[0].v_pointer = NULL;}static voidvalue_param_transform_value (const GValue *src_value, GValue *dest_value){ if (src_value->data[0].v_pointer && g_type_is_a (G_PARAM_SPEC_TYPE (dest_value->data[0].v_pointer), G_VALUE_TYPE (dest_value))) dest_value->data[0].v_pointer = g_param_spec_ref (src_value->data[0].v_pointer); else dest_value->data[0].v_pointer = NULL;}static gpointervalue_param_peek_pointer (const GValue *value){ return value->data[0].v_pointer;}static gchar*value_param_collect_value (GValue *value, guint n_collect_values, GTypeCValue *collect_values, guint collect_flags){ if (collect_values[0].v_pointer) { GParamSpec *param = collect_values[0].v_pointer; if (param->g_type_instance.g_class == NULL) return g_strconcat ("invalid unclassed param spec pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -