Wed, 19 Feb 2025 01:52:06 -0600
Implement Purple.ConversationMember.compare
Testing Done:
Ran the tests under valgrind and called in the turtles.
Bugs closed: PIDGIN-18051
Reviewed at https://reviews.imfreedom.org/r/3845/
--- a/libpurple/purpleconversationmember.c Tue Feb 18 23:34:01 2025 -0600 +++ b/libpurple/purpleconversationmember.c Wed Feb 19 01:52:06 2025 -0600 @@ -351,6 +351,45 @@ /****************************************************************************** * Public API *****************************************************************************/ +int +purple_conversation_member_compare(PurpleConversationMember *member1, + PurpleConversationMember *member2) +{ + const char *name1 = NULL; + const char *name2 = NULL; + int result = 0; + + /* Shortcut if the pointer is the same. */ + if(member1 == member2) { + return 0; + } + + /* NULL checks. */ + if(PURPLE_IS_CONVERSATION_MEMBER(member1) && + !PURPLE_IS_CONVERSATION_MEMBER(member2)) + { + return -1; + } + + if(!PURPLE_IS_CONVERSATION_MEMBER(member1) && + PURPLE_IS_CONVERSATION_MEMBER(member2)) + { + return 1; + } + + /* Check badges first. */ + result = purple_badges_compare(member1->badges, member2->badges); + if(result != 0) { + return result; + } + + /* Sort by the name for display. */ + name1 = purple_conversation_member_get_name_for_display(member1); + name2 = purple_conversation_member_get_name_for_display(member2); + + return purple_utf8_strcasecmp(name1, name2); +} + PurpleConversationMember * purple_conversation_member_new(PurpleContactInfo *info) { g_return_val_if_fail(PURPLE_IS_CONTACT_INFO(info), NULL);
--- a/libpurple/purpleconversationmember.h Tue Feb 18 23:34:01 2025 -0600 +++ b/libpurple/purpleconversationmember.h Wed Feb 19 01:52:06 2025 -0600 @@ -60,6 +60,25 @@ */ /** + * purple_conversation_member_compare: + * @member2: (nullable): the member to compare + * + * Compares two members for sorting order. + * + * This starts by calling [method@Badges.compare] on the + * [property@ConversationMember:badges] property and then checks the + * [property@ConversationMember:name-for-display]. + * + * Returns: less than zero if the first member should be sorted first, 0 if the + * two are equal or greater than zero if the second member should be + * sorted first. + * + * Since: 3.0 + */ +PURPLE_AVAILABLE_IN_3_0 +int purple_conversation_member_compare(PurpleConversationMember *member1, PurpleConversationMember *member2); + +/** * purple_conversation_member_new: * @info: The [class@Purple.ContactInfo] for the member. *
--- a/libpurple/tests/test_conversation_member.c Tue Feb 18 23:34:01 2025 -0600 +++ b/libpurple/tests/test_conversation_member.c Wed Feb 19 01:52:06 2025 -0600 @@ -345,6 +345,132 @@ } /****************************************************************************** + * Compare Tests + *****************************************************************************/ +static void +test_purple_conversation_member_compare_not_null__null(void) { + PurpleContactInfo *info = NULL; + PurpleConversationMember *member = NULL; + + info = purple_contact_info_new(NULL); + member = purple_conversation_member_new(info); + + g_assert_cmpint(purple_conversation_member_compare(member, NULL), <, 0); + + g_assert_finalize_object(member); + g_assert_finalize_object(info); +} + +static void +test_purple_conversation_member_compare_null__not_null(void) { + PurpleContactInfo *info = NULL; + PurpleConversationMember *member = NULL; + + info = purple_contact_info_new(NULL); + member = purple_conversation_member_new(info); + + g_assert_cmpint(purple_conversation_member_compare(NULL, member), >, 0); + + g_assert_finalize_object(member); + g_assert_finalize_object(info); +} + +static void +test_purple_conversation_member_compare_null__null(void) { + g_assert_cmpint(purple_conversation_member_compare(NULL, NULL), ==, 0); +} + +static void +test_purple_conversation_member_compare_same(void) { + PurpleContactInfo *info = NULL; + PurpleConversationMember *member = NULL; + + info = purple_contact_info_new(NULL); + member = purple_conversation_member_new(info); + + g_assert_cmpint(purple_conversation_member_compare(member, member), ==, 0); + + g_assert_finalize_object(member); + g_assert_finalize_object(info); +} + +static void +test_purple_conversation_member_compare_nickname__nickname(void) { + PurpleContactInfo *info1 = NULL; + PurpleContactInfo *info2 = NULL; + PurpleConversationMember *member1 = NULL; + PurpleConversationMember *member2 = NULL; + int result = 0; + + info1 = purple_contact_info_new(NULL); + member1 = purple_conversation_member_new(info1); + purple_conversation_member_set_nickname(member1, "aaa"); + + info2 = purple_contact_info_new(NULL); + member2 = purple_conversation_member_new(info2); + purple_conversation_member_set_nickname(member2, "zzz"); + + result = purple_conversation_member_compare(member1, member2); + g_assert_cmpint(result, <, 0); + + result = purple_conversation_member_compare(member2, member1); + g_assert_cmpint(result, >, 0); + + purple_conversation_member_set_nickname(member2, "aaa"); + result = purple_conversation_member_compare(member1, member2); + g_assert_cmpint(result, ==, 0); + + g_assert_finalize_object(member1); + g_assert_finalize_object(member2); + g_assert_finalize_object(info1); + g_assert_finalize_object(info2); +} + +static void +test_purple_conversation_member_compare_badges__nickname(void) { + PurpleBadge *badge = NULL; + PurpleBadges *badges = NULL; + PurpleContactInfo *info1 = NULL; + PurpleContactInfo *info2 = NULL; + PurpleConversationMember *member1 = NULL; + PurpleConversationMember *member2 = NULL; + gboolean removed = FALSE; + int result = 0; + + info1 = purple_contact_info_new(NULL); + member1 = purple_conversation_member_new(info1); + purple_conversation_member_set_nickname(member1, "zzz"); + badges = purple_conversation_member_get_badges(member1); + badge = purple_badge_new("id", 1000, "icon", "I"); + purple_badges_add_badge(badges, badge); + g_clear_object(&badge); + + info2 = purple_contact_info_new(NULL); + member2 = purple_conversation_member_new(info2); + purple_conversation_member_set_nickname(member2, "aaa"); + + result = purple_conversation_member_compare(member1, member2); + g_assert_cmpint(result, <, 0); + + result = purple_conversation_member_compare(member2, member1); + g_assert_cmpint(result, >, 0); + + /* Remove the badge and make sure member2 is sorted first because its + * nickname sorts first. + */ + removed = purple_badges_remove_badge(badges, "id"); + g_assert_true(removed); + + result = purple_conversation_member_compare(member1, member2); + g_assert_cmpint(result, >, 0); + + g_assert_finalize_object(member1); + g_assert_finalize_object(member2); + g_assert_finalize_object(info1); + g_assert_finalize_object(info2); +} + +/****************************************************************************** * Main *****************************************************************************/ int @@ -373,6 +499,18 @@ g_test_add_func("/conversation-member/matches/contact_info", test_purple_conversation_member_matches_contact_info); + g_test_add_func("/conversation-member/compare/not_null__null", + test_purple_conversation_member_compare_not_null__null); + g_test_add_func("/conversation-member/compare/null__not_null", + test_purple_conversation_member_compare_null__not_null); + g_test_add_func("/conversation-member/compare/null__null", + test_purple_conversation_member_compare_null__null); + g_test_add_func("/conversation-member/compare/same", + test_purple_conversation_member_compare_same); + g_test_add_func("/conversation-member/compare/nickname__nickname", + test_purple_conversation_member_compare_nickname__nickname); + g_test_add_func("/conversation-member/compare/badges__nickname", + test_purple_conversation_member_compare_badges__nickname); return g_test_run(); }