From c4718596c27feafc793c8f3f04f73adb053ab724 Mon Sep 17 00:00:00 2001 From: Emmanuel Fleury Date: Fri, 14 Nov 2025 18:11:19 +0100 Subject: [PATCH] gobject: Make enum/flags value lookups case-insensitive Make g_enum_get_value_by_name(), g_flags_get_value_by_name(), g_enum_get_value_by_nick() and g_flags_get_value_by_nick() perform ASCII case-insensitive comparisons when matching names and nicks. This aligns behavior with common expectations for user-visible nicks and reduces rejections of mixed-case inputs. Implementation switches from strcmp() to strcmp_ignore_case() when comparing the provided name/nick to registered values. This is a minor behavior change that only broadens accepted input. Types with values that differ only by case are now allowed. Tests: Extend gobject/tests/enums.c to cover mixed-case lookups for both enums and flags (names and nicks). Fixes: #74 --- gobject/genums.c | 43 +++++++++++++++++++++++++++++++++++-------- gobject/tests/enums.c | 4 ++++ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/gobject/genums.c b/gobject/genums.c index 97980e1af..2415ba0e3 100644 --- a/gobject/genums.c +++ b/gobject/genums.c @@ -351,6 +351,33 @@ g_flags_class_init (GFlagsClass *class, } } +/* Internal function to compare strings without taking into account + * character case and more... in order to ease the look ups. */ +static int +strcmp_ignore_case (const char *str1, const char *str2) +{ + const char *ptr1 = str1, *ptr2 = str2; + char c1, c2; + + do + { + /* Normalize to lower case */ + c1 = g_ascii_tolower (*ptr1++); + c2 = g_ascii_tolower (*ptr2++); + + /* End of either string */ + if (c1 == '\0' || c2 == '\0') + return c1 - c2; + + /* Normalize '-' to '_' */ + c1 = (c1 == '-') ? '_' : c1; + c2 = (c2 == '-') ? '_' : c2; + } + while (c1 == c2); + + return c1 - c2; +} + /** * g_enum_get_value_by_name: * @enum_class: a #GEnumClass @@ -374,8 +401,8 @@ g_enum_get_value_by_name (GEnumClass *enum_class, GEnumValue *enum_value; for (enum_value = enum_class->values; enum_value->value_name; enum_value++) - if (strcmp (name, enum_value->value_name) == 0) - return enum_value; + if (strcmp_ignore_case (name, enum_value->value_name) == 0) + return enum_value; } return NULL; @@ -403,8 +430,8 @@ g_flags_get_value_by_name (GFlagsClass *flags_class, GFlagsValue *flags_value; for (flags_value = flags_class->values; flags_value->value_name; flags_value++) - if (strcmp (name, flags_value->value_name) == 0) - return flags_value; + if (strcmp_ignore_case (name, flags_value->value_name) == 0) + return flags_value; } return NULL; @@ -433,8 +460,8 @@ g_enum_get_value_by_nick (GEnumClass *enum_class, GEnumValue *enum_value; for (enum_value = enum_class->values; enum_value->value_name; enum_value++) - if (enum_value->value_nick && strcmp (nick, enum_value->value_nick) == 0) - return enum_value; + if (enum_value->value_nick && strcmp_ignore_case (nick, enum_value->value_nick) == 0) + return enum_value; } return NULL; @@ -462,8 +489,8 @@ g_flags_get_value_by_nick (GFlagsClass *flags_class, GFlagsValue *flags_value; for (flags_value = flags_class->values; flags_value->value_nick; flags_value++) - if (flags_value->value_nick && strcmp (nick, flags_value->value_nick) == 0) - return flags_value; + if (flags_value->value_nick && strcmp_ignore_case (nick, flags_value->value_nick) == 0) + return flags_value; } return NULL; diff --git a/gobject/tests/enums.c b/gobject/tests/enums.c index 49741914c..fe4907fea 100644 --- a/gobject/tests/enums.c +++ b/gobject/tests/enums.c @@ -41,12 +41,14 @@ test_enum_basic (void) val = g_enum_get_value_by_name (class, "the third value"); g_assert_nonnull (val); g_assert_cmpint (val->value, ==, 3); + g_assert_true (g_enum_get_value_by_name (class, "The Third Value") == val); val = g_enum_get_value_by_name (class, "the color purple"); g_assert_null (val); val = g_enum_get_value_by_nick (class, "one"); g_assert_nonnull (val); g_assert_cmpint (val->value, ==, 1); + g_assert_true (g_enum_get_value_by_nick (class, "One") == val); val = g_enum_get_value_by_nick (class, "purple"); g_assert_null (val); @@ -118,6 +120,7 @@ test_flags_basic (void) val = g_flags_get_value_by_name (class, "the third flag"); g_assert_nonnull (val); + g_assert_true (g_flags_get_value_by_name (class, "The Third Flag") == val); g_assert_cmpint (val->value, ==, 8); val = g_flags_get_value_by_name (class, "the color purple"); g_assert_null (val); @@ -125,6 +128,7 @@ test_flags_basic (void) val = g_flags_get_value_by_nick (class, "one"); g_assert_nonnull (val); g_assert_cmpint (val->value, ==, 1); + g_assert_true (g_flags_get_value_by_nick (class, "One") == val); val = g_flags_get_value_by_nick (class, "purple"); g_assert_null (val);