[glib/param-speedups: 6/7] param: Add a value_is_valid vfunc




commit dff7159fa509488d5819fe23777d9642373a41b9
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat May 14 22:35:10 2022 -0400

    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.

 gobject/gparam.h      |  11 ++-
 gobject/gparamspecs.c | 246 +++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 244 insertions(+), 13 deletions(-)
---
diff --git a/gobject/gparam.h b/gobject/gparam.h
index e0f316682d..fea6e502c8 100644
--- a/gobject/gparam.h
+++ b/gobject/gparam.h
@@ -236,7 +236,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.
+ *
  * The class structure for the GParamSpec type.
  * Normally, GParamSpec classes are filled by
  * g_param_type_register_static().
@@ -257,8 +260,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:
diff --git a/gobject/gparamspecs.c b/gobject/gparamspecs.c
index c7879842b1..b8659bb989 100644
--- a/gobject/gparamspecs.c
+++ b/gobject/gparamspecs.c
@@ -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)
@@ -643,6 +778,23 @@ param_string_set_default (GParamSpec *pspec,
   value->data[0].v_pointer = g_strdup (G_PARAM_SPEC_STRING (pspec)->default_value);
 }
 
+static gboolean
+param_string_is_valid (GParamSpec   *pspec,
+                       const GValue *value)
+{
+  GParamSpecString *sspec = G_PARAM_SPEC_STRING (pspec);
+
+  if (sspec->cset_first == NULL && sspec->cset_nth == NULL)
+    return TRUE;
+
+  /* We don't actually check the charset here - in practice,
+   * virtually no GParamSpecString has them set, and we can
+   * just rely on object_set_property in gobject.c to do
+   * the value transformation if we return FALSE here.
+   */
+  return FALSE;
+}
+
 static gboolean
 param_string_validate (GParamSpec *pspec,
                       GValue     *value)
@@ -728,6 +880,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 +946,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 +1123,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 +1195,18 @@ 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);
+  
+  if (G_PARAM_SPEC_GET_CLASS (ospec->overridden)->value_is_valid)
+    return G_PARAM_SPEC_GET_CLASS (ospec->overridden)->value_is_valid (ospec->overridden, value);
+
+  return FALSE;
+}
+
 static gboolean
 param_override_validate (GParamSpec *pspec,
                         GValue     *value)
@@ -1066,6 +1240,16 @@ 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 g_type_is_a (gtype, tspec->is_a_type);
+}
+
 static gboolean
 param_gtype_validate (GParamSpec *pspec,
                      GValue     *value)
@@ -1126,6 +1310,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 +1378,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 +1416,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 +1435,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 +1454,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 +1473,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 +1492,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 +1511,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 +1530,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 +1549,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 +1568,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 +1587,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 +1606,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 +1625,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 +1644,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 +1663,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 +1682,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 +1701,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 +1734,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 +1775,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 +1794,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 +1814,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 +1833,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);
   }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]