summaryrefslogtreecommitdiff
path: root/gobject/gparamspecs.c
diff options
context:
space:
mode:
authorPhilip Withnall <withnall@endlessm.com>2018-05-04 10:13:13 +0100
committerPhilip Withnall <withnall@endlessm.com>2018-05-04 18:17:59 +0100
commitcc4de801c9643b62c5566d4d9dc3439ca801a4e6 (patch)
tree7b87ea3f45146bf47ac478e924818bfcbc6431d0 /gobject/gparamspecs.c
parenta06117d0623ec0ddef895db605bac09460daae15 (diff)
downloadglib-cc4de801c9643b62c5566d4d9dc3439ca801a4e6.tar.gz
gobject: Reimplement g_param_values_cmp() for GParamSpecVariant
The existing implementation was completely incorrect (despite the fix in commit 566e64a66) — it always compared GVariants by pointer, rather than by value. Reimplement it to compare them by value where possible, depending on their type. The core of this implementation is g_variant_compare(). See the documentation and tests for further details of the new sort order. This adds documentation and tests. Signed-off-by: Philip Withnall <withnall@endlessm.com> https://bugzilla.gnome.org/show_bug.cgi?id=795735
Diffstat (limited to 'gobject/gparamspecs.c')
-rw-r--r--gobject/gparamspecs.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/gobject/gparamspecs.c b/gobject/gparamspecs.c
index 8c285fa1c..d76e12f55 100644
--- a/gobject/gparamspecs.c
+++ b/gobject/gparamspecs.c
@@ -1147,6 +1147,20 @@ param_variant_validate (GParamSpec *pspec,
return FALSE;
}
+/* g_variant_compare() can only be used with scalar types. */
+static gboolean
+variant_is_incomparable (GVariant *v)
+{
+ GVariantClass v_class = g_variant_classify (v);
+
+ return (v_class == G_VARIANT_CLASS_HANDLE ||
+ v_class == G_VARIANT_CLASS_VARIANT ||
+ v_class == G_VARIANT_CLASS_MAYBE||
+ v_class == G_VARIANT_CLASS_ARRAY ||
+ v_class == G_VARIANT_CLASS_TUPLE ||
+ v_class == G_VARIANT_CLASS_DICT_ENTRY);
+}
+
static gint
param_variant_values_cmp (GParamSpec *pspec,
const GValue *value1,
@@ -1155,7 +1169,19 @@ param_variant_values_cmp (GParamSpec *pspec,
GVariant *v1 = value1->data[0].v_pointer;
GVariant *v2 = value2->data[0].v_pointer;
- return v1 < v2 ? -1 : v2 > v1;
+ if (v1 == NULL && v2 == NULL)
+ return 0;
+ else if (v1 == NULL && v2 != NULL)
+ return -1;
+ else if (v1 != NULL && v2 == NULL)
+ return 1;
+
+ if (!g_variant_type_equal (g_variant_get_type (v1), g_variant_get_type (v2)) ||
+ variant_is_incomparable (v1) ||
+ variant_is_incomparable (v2))
+ return g_variant_equal (v1, v2) ? 0 : (v1 < v2 ? -1 : 1);
+
+ return g_variant_compare (v1, v2);
}
/* --- type initialization --- */