diff options
author | Philip Withnall <withnall@endlessm.com> | 2018-05-04 10:13:13 +0100 |
---|---|---|
committer | Philip Withnall <withnall@endlessm.com> | 2018-05-04 18:17:59 +0100 |
commit | cc4de801c9643b62c5566d4d9dc3439ca801a4e6 (patch) | |
tree | 7b87ea3f45146bf47ac478e924818bfcbc6431d0 /gobject/gparamspecs.c | |
parent | a06117d0623ec0ddef895db605bac09460daae15 (diff) | |
download | glib-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.c | 28 |
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 --- */ |