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
This commit is contained in:
Emmanuel Fleury
2025-11-14 18:11:19 +01:00
parent 298fa45f90
commit c4718596c2
2 changed files with 39 additions and 8 deletions

View File

@@ -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;

View File

@@ -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);