param: Add a value_is_valid vfunc

In constrast to value_validate, this one does not
modify the passed-in value, so we can avoid the cost
of copying the GValue beforehand.
It is optional, but we set it for most of the
builtin pspec types.
This commit is contained in:
Matthias Clasen 2022-05-14 22:35:10 -04:00
parent 3d3162c202
commit bdc8b025c5
2 changed files with 248 additions and 13 deletions

View File

@ -242,7 +242,10 @@ struct _GParamSpec
* g_param_value_validate().
* @values_cmp: Compares @value1 with @value2 according to this type
* (recommended, the default is memcmp()), see g_param_values_cmp().
*
* @value_is_valid: Checks if contents of @value comply with the specifications
* set out by this type, without modifying the value. This vfunc is optional.
* If it isn't set, GObject will use @value_validate. Since 2.74
*
* The class structure for the GParamSpec type.
* Normally, GParamSpec classes are filled by
* g_param_type_register_static().
@ -263,8 +266,12 @@ struct _GParamSpecClass
gint (*values_cmp) (GParamSpec *pspec,
const GValue *value1,
const GValue *value2);
gboolean (*value_is_valid) (GParamSpec *pspec,
const GValue *value);
/*< private >*/
gpointer dummy[4];
gpointer dummy[3];
};
/**
* GParameter:

View File

@ -80,6 +80,16 @@ param_char_set_default (GParamSpec *pspec,
value->data[0].v_int = G_PARAM_SPEC_CHAR (pspec)->default_value;
}
static gboolean
param_char_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecChar *cspec = G_PARAM_SPEC_CHAR (pspec);
gint oval = value->data[0].v_int;
return cspec->minimum <= oval && oval <= cspec->maximum;
}
static gboolean
param_char_validate (GParamSpec *pspec,
GValue *value)
@ -109,6 +119,16 @@ param_uchar_set_default (GParamSpec *pspec,
value->data[0].v_uint = G_PARAM_SPEC_UCHAR (pspec)->default_value;
}
static gboolean
param_uchar_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecUChar *uspec = G_PARAM_SPEC_UCHAR (pspec);
guint oval = value->data[0].v_uint;
return uspec->minimum <= oval && oval <= uspec->maximum;
}
static gboolean
param_uchar_validate (GParamSpec *pspec,
GValue *value)
@ -128,6 +148,15 @@ param_boolean_set_default (GParamSpec *pspec,
value->data[0].v_int = G_PARAM_SPEC_BOOLEAN (pspec)->default_value;
}
static gboolean
param_boolean_is_valid (GParamSpec *pspec,
const GValue *value)
{
int oval = value->data[0].v_int;
return oval == FALSE || oval == TRUE;
}
static gboolean
param_boolean_validate (GParamSpec *pspec,
GValue *value)
@ -156,6 +185,16 @@ param_int_set_default (GParamSpec *pspec,
value->data[0].v_int = G_PARAM_SPEC_INT (pspec)->default_value;
}
static gboolean
param_int_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecInt *ispec = G_PARAM_SPEC_INT (pspec);
int oval = value->data[0].v_int;
return ispec->minimum <= oval && oval <= ispec->maximum;
}
static gboolean
param_int_validate (GParamSpec *pspec,
GValue *value)
@ -196,6 +235,16 @@ param_uint_set_default (GParamSpec *pspec,
value->data[0].v_uint = G_PARAM_SPEC_UINT (pspec)->default_value;
}
static gboolean
param_uint_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecUInt *uspec = G_PARAM_SPEC_UINT (pspec);
guint oval = value->data[0].v_uint;
return uspec->minimum <= oval && oval <= uspec->maximum;
}
static gboolean
param_uint_validate (GParamSpec *pspec,
GValue *value)
@ -241,6 +290,16 @@ param_long_set_default (GParamSpec *pspec,
value->data[0].v_long = G_PARAM_SPEC_LONG (pspec)->default_value;
}
static gboolean
param_long_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecLong *lspec = G_PARAM_SPEC_LONG (pspec);
glong oval = value->data[0].v_long;
return lspec->minimum <= oval && oval <= lspec->maximum;
}
static gboolean
param_long_validate (GParamSpec *pspec,
GValue *value)
@ -285,6 +344,16 @@ param_ulong_set_default (GParamSpec *pspec,
value->data[0].v_ulong = G_PARAM_SPEC_ULONG (pspec)->default_value;
}
static gboolean
param_ulong_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecULong *uspec = G_PARAM_SPEC_ULONG (pspec);
gulong oval = value->data[0].v_ulong;
return uspec->minimum <= oval && oval <= uspec->maximum;
}
static gboolean
param_ulong_validate (GParamSpec *pspec,
GValue *value)
@ -325,6 +394,16 @@ param_int64_set_default (GParamSpec *pspec,
value->data[0].v_int64 = G_PARAM_SPEC_INT64 (pspec)->default_value;
}
static gboolean
param_int64_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecInt64 *lspec = G_PARAM_SPEC_INT64 (pspec);
gint64 oval = value->data[0].v_int64;
return lspec->minimum <= oval && oval <= lspec->maximum;
}
static gboolean
param_int64_validate (GParamSpec *pspec,
GValue *value)
@ -365,6 +444,16 @@ param_uint64_set_default (GParamSpec *pspec,
value->data[0].v_uint64 = G_PARAM_SPEC_UINT64 (pspec)->default_value;
}
static gboolean
param_uint64_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecUInt64 *uspec = G_PARAM_SPEC_UINT64 (pspec);
guint64 oval = value->data[0].v_uint64;
return uspec->minimum <= oval && oval <= uspec->maximum;
}
static gboolean
param_uint64_validate (GParamSpec *pspec,
GValue *value)
@ -403,6 +492,13 @@ param_unichar_set_default (GParamSpec *pspec,
value->data[0].v_uint = G_PARAM_SPEC_UNICHAR (pspec)->default_value;
}
static gboolean
param_unichar_is_valid (GParamSpec *pspec,
const GValue *value)
{
return g_unichar_validate (value->data[0].v_uint);
}
static gboolean
param_unichar_validate (GParamSpec *pspec,
GValue *value)
@ -461,6 +557,16 @@ param_enum_set_default (GParamSpec *pspec,
value->data[0].v_long = G_PARAM_SPEC_ENUM (pspec)->default_value;
}
static gboolean
param_enum_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
glong oval = value->data[0].v_long;
return g_enum_get_value (espec->enum_class, oval) != NULL;
}
static gboolean
param_enum_validate (GParamSpec *pspec,
GValue *value)
@ -506,6 +612,15 @@ param_flags_set_default (GParamSpec *pspec,
value->data[0].v_ulong = G_PARAM_SPEC_FLAGS (pspec)->default_value;
}
static gboolean
param_flags_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecFlags *fspec = G_PARAM_SPEC_FLAGS (pspec);
gulong oval = value->data[0].v_ulong;
return (oval & ~fspec->flags_class->mask) == 0;
}
static gboolean
param_flags_validate (GParamSpec *pspec,
GValue *value)
@ -539,6 +654,16 @@ param_float_set_default (GParamSpec *pspec,
value->data[0].v_float = G_PARAM_SPEC_FLOAT (pspec)->default_value;
}
static gboolean
param_float_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecFloat *fspec = G_PARAM_SPEC_FLOAT (pspec);
gfloat oval = value->data[0].v_float;
return fspec->minimum <= oval && oval <= fspec->maximum;
}
static gboolean
param_float_validate (GParamSpec *pspec,
GValue *value)
@ -582,6 +707,16 @@ param_double_set_default (GParamSpec *pspec,
value->data[0].v_double = G_PARAM_SPEC_DOUBLE (pspec)->default_value;
}
static gboolean
param_double_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecDouble *dspec = G_PARAM_SPEC_DOUBLE (pspec);
gfloat oval = value->data[0].v_double;
return dspec->minimum <= oval && oval <= dspec->maximum;
}
static gboolean
param_double_validate (GParamSpec *pspec,
GValue *value)
@ -702,6 +837,29 @@ param_string_validate (GParamSpec *pspec,
return changed;
}
static gboolean
param_string_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecString *sspec = G_PARAM_SPEC_STRING (pspec);
gboolean ret = TRUE;
if (sspec->cset_first != NULL || sspec->cset_nth != NULL ||
sspec->ensure_non_null || sspec->null_fold_if_empty)
{
GValue tmp_value = G_VALUE_INIT;
g_value_init (&tmp_value, G_VALUE_TYPE (value));
g_value_copy (value, &tmp_value);
ret = !param_string_validate (pspec, &tmp_value);
g_value_unset (&tmp_value);
}
return ret;
}
static gint
param_string_values_cmp (GParamSpec *pspec,
const GValue *value1,
@ -728,6 +886,15 @@ param_param_set_default (GParamSpec *pspec,
value->data[0].v_pointer = NULL;
}
static gboolean
param_param_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpec *param = value->data[0].v_pointer;
return g_value_type_compatible (G_PARAM_SPEC_TYPE (param), G_PARAM_SPEC_VALUE_TYPE (pspec));
}
static gboolean
param_param_validate (GParamSpec *pspec,
GValue *value)
@ -785,16 +952,6 @@ param_pointer_set_default (GParamSpec *pspec,
value->data[0].v_pointer = NULL;
}
static gboolean
param_pointer_validate (GParamSpec *pspec,
GValue *value)
{
/* GParamSpecPointer *spec = G_PARAM_SPEC_POINTER (pspec); */
guint changed = 0;
return changed;
}
static gint
param_pointer_values_cmp (GParamSpec *pspec,
const GValue *value1,
@ -972,6 +1129,17 @@ param_object_set_default (GParamSpec *pspec,
value->data[0].v_pointer = NULL;
}
static gboolean
param_object_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec);
GObject *object = value->data[0].v_pointer;
return object &&
g_value_type_compatible (G_OBJECT_TYPE (object), G_PARAM_SPEC_VALUE_TYPE (ospec));
}
static gboolean
param_object_validate (GParamSpec *pspec,
GValue *value)
@ -1033,6 +1201,15 @@ param_override_set_default (GParamSpec *pspec,
g_param_value_set_default (ospec->overridden, value);
}
static gboolean
param_override_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
return g_param_value_is_valid (ospec->overridden, value);
}
static gboolean
param_override_validate (GParamSpec *pspec,
GValue *value)
@ -1066,6 +1243,17 @@ param_gtype_set_default (GParamSpec *pspec,
value->data[0].v_pointer = GSIZE_TO_POINTER (tspec->is_a_type);
}
static gboolean
param_gtype_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecGType *tspec = G_PARAM_SPEC_GTYPE (pspec);
GType gtype = GPOINTER_TO_SIZE (value->data[0].v_pointer);
return tspec->is_a_type == G_TYPE_NONE ||
g_type_is_a (gtype, tspec->is_a_type);
}
static gboolean
param_gtype_validate (GParamSpec *pspec,
GValue *value)
@ -1126,6 +1314,19 @@ param_variant_set_default (GParamSpec *pspec,
value->data[1].v_uint |= G_VALUE_NOCOPY_CONTENTS;
}
static gboolean
param_variant_is_valid (GParamSpec *pspec,
const GValue *value)
{
GParamSpecVariant *vspec = G_PARAM_SPEC_VARIANT (pspec);
GVariant *variant = value->data[0].v_pointer;
if (variant == NULL)
return vspec->default_value == NULL;
else
return g_variant_is_of_type (variant, vspec->type);
}
static gboolean
param_variant_validate (GParamSpec *pspec,
GValue *value)
@ -1181,6 +1382,13 @@ param_variant_values_cmp (GParamSpec *pspec,
}
/* --- type initialization --- */
#define set_is_valid_vfunc(type,func) { \
GParamSpecClass *class = g_type_class_ref (type); \
class->value_is_valid = func; \
g_type_class_unref (class); \
}
GType *g_param_spec_types = NULL;
void
@ -1212,6 +1420,7 @@ _g_param_spec_types_init (void)
param_int_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamChar"), &pspec_info);
set_is_valid_vfunc (type, param_char_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_CHAR);
}
@ -1230,6 +1439,7 @@ _g_param_spec_types_init (void)
param_uint_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamUChar"), &pspec_info);
set_is_valid_vfunc (type, param_uchar_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_UCHAR);
}
@ -1248,6 +1458,7 @@ _g_param_spec_types_init (void)
param_int_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamBoolean"), &pspec_info);
set_is_valid_vfunc (type, param_boolean_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_BOOLEAN);
}
@ -1266,6 +1477,7 @@ _g_param_spec_types_init (void)
param_int_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamInt"), &pspec_info);
set_is_valid_vfunc (type, param_int_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_INT);
}
@ -1284,6 +1496,7 @@ _g_param_spec_types_init (void)
param_uint_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamUInt"), &pspec_info);
set_is_valid_vfunc (type, param_uint_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_UINT);
}
@ -1302,6 +1515,7 @@ _g_param_spec_types_init (void)
param_long_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamLong"), &pspec_info);
set_is_valid_vfunc (type, param_long_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_LONG);
}
@ -1320,6 +1534,7 @@ _g_param_spec_types_init (void)
param_ulong_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamULong"), &pspec_info);
set_is_valid_vfunc (type, param_ulong_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_ULONG);
}
@ -1338,6 +1553,7 @@ _g_param_spec_types_init (void)
param_int64_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamInt64"), &pspec_info);
set_is_valid_vfunc (type, param_int64_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_INT64);
}
@ -1356,6 +1572,7 @@ _g_param_spec_types_init (void)
param_uint64_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamUInt64"), &pspec_info);
set_is_valid_vfunc (type, param_uint64_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_UINT64);
}
@ -1374,6 +1591,7 @@ _g_param_spec_types_init (void)
param_unichar_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamUnichar"), &pspec_info);
set_is_valid_vfunc (type, param_unichar_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_UNICHAR);
}
@ -1392,6 +1610,7 @@ _g_param_spec_types_init (void)
param_long_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamEnum"), &pspec_info);
set_is_valid_vfunc (type, param_enum_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_ENUM);
}
@ -1410,6 +1629,7 @@ _g_param_spec_types_init (void)
param_ulong_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamFlags"), &pspec_info);
set_is_valid_vfunc (type, param_flags_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_FLAGS);
}
@ -1428,6 +1648,7 @@ _g_param_spec_types_init (void)
param_float_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamFloat"), &pspec_info);
set_is_valid_vfunc (type, param_float_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_FLOAT);
}
@ -1446,6 +1667,7 @@ _g_param_spec_types_init (void)
param_double_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamDouble"), &pspec_info);
set_is_valid_vfunc (type, param_double_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_DOUBLE);
}
@ -1464,6 +1686,7 @@ _g_param_spec_types_init (void)
param_string_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamString"), &pspec_info);
set_is_valid_vfunc (type, param_string_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_STRING);
}
@ -1482,6 +1705,7 @@ _g_param_spec_types_init (void)
param_pointer_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamParam"), &pspec_info);
set_is_valid_vfunc (type, param_param_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_PARAM);
}
@ -1514,7 +1738,7 @@ _g_param_spec_types_init (void)
G_TYPE_POINTER, /* value_type */
NULL, /* finalize */
param_pointer_set_default, /* value_set_default */
param_pointer_validate, /* value_validate */
NULL,
param_pointer_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamPointer"), &pspec_info);
@ -1555,6 +1779,7 @@ _g_param_spec_types_init (void)
param_object_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamObject"), &pspec_info);
set_is_valid_vfunc (type, param_object_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_OBJECT);
}
@ -1573,6 +1798,7 @@ _g_param_spec_types_init (void)
param_override_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamOverride"), &pspec_info);
set_is_valid_vfunc (type, param_override_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_OVERRIDE);
}
@ -1592,6 +1818,7 @@ _g_param_spec_types_init (void)
};
pspec_info.value_type = G_TYPE_GTYPE;
type = g_param_type_register_static (g_intern_static_string ("GParamGType"), &pspec_info);
set_is_valid_vfunc (type, param_gtype_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_GTYPE);
}
@ -1610,6 +1837,7 @@ _g_param_spec_types_init (void)
param_variant_values_cmp, /* values_cmp */
};
type = g_param_type_register_static (g_intern_static_string ("GParamVariant"), &pspec_info);
set_is_valid_vfunc (type, param_variant_is_valid);
*spec_types++ = type;
g_assert (type == G_TYPE_PARAM_VARIANT);
}