Mercurial > pidgin
changeset 31707:47f7b8ca6149
conversation: O(1) purple_conv_chat_cb_find
I also deprecated what seems like a useless function. The
ui_data is to implement constant-time lookups for the room
list in Pidgin.
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Mon, 20 Jun 2011 05:24:30 +0000 |
parents | bb77a9ceca17 |
children | 5847a4c212f0 |
files | ChangeLog.API libpurple/conversation.c libpurple/conversation.h |
diffstat | 3 files changed, 69 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog.API Mon Jun 20 05:11:53 2011 +0000 +++ b/ChangeLog.API Mon Jun 20 05:24:30 2011 +0000 @@ -1,6 +1,17 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul version 2.9.0 (MM/DD/YYYY): + libpurple: + Added: + * Hash table and equivalence function to PurpleConvChat struct, + which makes purple_conv_chat_cb_find O(1). The equivalence + function should only be set by a prpl, and must only be set + before any occupants are in the room. + * ui_data opaque pointer to PurpleConvChatBuddy struct. + + Deprecated: + * purple_conv_chat_set_users + * PurpleConvChat in_room list version 2.8.0 (06/07/2011): libpurple:
--- a/libpurple/conversation.c Mon Jun 20 05:11:53 2011 +0000 +++ b/libpurple/conversation.c Mon Jun 20 05:24:30 2011 +0000 @@ -70,6 +70,25 @@ g_free(hc); } +static guint _purple_conversation_user_hash(gconstpointer data) +{ + const gchar *name = data; + gchar *casefold, *collated; + guint hash; + + casefold = g_utf8_casefold(name, -1); + collated = g_utf8_collate_key(casefold, -1); + hash = g_str_hash(collated); + g_free(collated); + g_free(casefold); + return hash; +} + +static gboolean _purple_conversation_user_equal(gconstpointer a, gconstpointer b) +{ + return !purple_utf8_strcasecmp(a, b); +} + void purple_conversations_set_ui_ops(PurpleConversationUiOps *ops) { @@ -393,6 +412,10 @@ conv->u.chat = g_new0(PurpleConvChat, 1); conv->u.chat->conv = conv; + conv->u.chat->user_hash_func = _purple_conversation_user_hash; + conv->u.chat->user_eq_func = _purple_conversation_user_equal; + conv->u.chat->users = g_hash_table_new_full(_purple_conversation_user_hash, + _purple_conversation_user_equal, NULL, NULL); PURPLE_DBUS_REGISTER_POINTER(conv->u.chat, PurpleConvChat); chats = g_list_prepend(chats, conv); @@ -547,6 +570,8 @@ conv->u.im = NULL; } else if (conv->type == PURPLE_CONV_TYPE_CHAT) { + g_hash_table_destroy(conv->u.chat->users); + conv->u.chat->users = NULL; g_list_foreach(conv->u.chat->in_room, (GFunc)purple_conv_chat_cb_destroy, NULL); g_list_free(conv->u.chat->in_room); @@ -1677,9 +1702,9 @@ cbuddy = purple_conv_chat_cb_new(user, alias, flag); cbuddy->buddy = purple_find_buddy(conv->account, user) != NULL; - /* This seems dumb. Why should we set users thousands of times? */ - purple_conv_chat_set_users(chat, - g_list_prepend(chat->in_room, cbuddy)); + + chat->in_room = g_list_prepend(chat->in_room, cbuddy); + g_hash_table_replace(chat->users, cbuddy->name, cbuddy); cbuddies = g_list_prepend(cbuddies, cbuddy); @@ -1771,8 +1796,9 @@ flags = purple_conv_chat_user_get_flags(chat, old_user); cb = purple_conv_chat_cb_new(new_user, new_alias, flags); cb->buddy = purple_find_buddy(conv->account, new_user) != NULL; - purple_conv_chat_set_users(chat, - g_list_prepend(chat->in_room, cb)); + + chat->in_room = g_list_prepend(chat->in_room, cb); + g_hash_table_replace(chat->users, cb->name, cb); if (ops != NULL && ops->chat_rename_user != NULL) ops->chat_rename_user(conv, old_user, new_user, new_alias); @@ -1780,8 +1806,8 @@ cb = purple_conv_chat_cb_find(chat, old_user); if (cb) { - purple_conv_chat_set_users(chat, - g_list_remove(chat->in_room, cb)); + chat->in_room = g_list_remove(chat->in_room, cb); + g_hash_table_remove(chat->users, cb->name); purple_conv_chat_cb_destroy(cb); } @@ -1874,8 +1900,8 @@ cb = purple_conv_chat_cb_find(chat, user); if (cb) { - purple_conv_chat_set_users(chat, - g_list_remove(chat->in_room, cb)); + chat->in_room = g_list_remove(chat->in_room, cb); + g_hash_table_remove(chat->users, cb); purple_conv_chat_cb_destroy(cb); } @@ -1943,6 +1969,8 @@ g_list_free(names); } + g_hash_table_remove_all(chat->users); + for (l = users; l; l = l->next) { PurpleConvChatBuddy *cb = l->data; @@ -1956,7 +1984,7 @@ } g_list_free(users); - purple_conv_chat_set_users(chat, NULL); + chat->in_room = NULL; } @@ -2146,19 +2174,10 @@ PurpleConvChatBuddy * purple_conv_chat_cb_find(PurpleConvChat *chat, const char *name) { - GList *l; - PurpleConvChatBuddy *cb = NULL; - g_return_val_if_fail(chat != NULL, NULL); g_return_val_if_fail(name != NULL, NULL); - for (l = purple_conv_chat_get_users(chat); l; l = l->next) { - cb = l->data; - if (!g_utf8_collate(cb->name, name)) - return cb; - } - - return NULL; + return g_hash_table_lookup(chat->users, name); } void
--- a/libpurple/conversation.h Mon Jun 20 05:11:53 2011 +0000 +++ b/libpurple/conversation.h Mon Jun 20 05:24:30 2011 +0000 @@ -271,7 +271,9 @@ { PurpleConversation *conv; /**< The parent conversation. */ - GList *in_room; /**< The users in the room. */ + GList *in_room; /**< The users in the room. + * @deprecated Will be removed in 3.0.0 + */ GList *ignored; /**< Ignored users. */ char *who; /**< The person who set the topic. */ char *topic; /**< The topic. */ @@ -279,6 +281,19 @@ char *nick; /**< Your nick in this chat. */ gboolean left; /**< We left the chat and kept the window open */ + GHashTable *users; /**< Hash table of the users in the room. + * @since 2.9.0 + */ + GHashFunc user_hash_func; /**< Function used to hash entries into + * the users hash. Defaults to a + * case-insensitive collation function. + * @since 2.9.0 + */ + GEqualFunc user_eq_func; /**< Function used for equality in the + * users hash. Defaults to a wrapper + * around purple_utf8_strcasecmp. + * @since 2.9.0 + */ }; /** @@ -304,6 +319,7 @@ GHashTable *attributes; /**< A hash table of attributes about the user, such as * real name, user@host, etc. */ + gpointer ui_data; /** < The UI can put whatever it wants here. */ }; /** @@ -1065,6 +1081,8 @@ * @param users The list of users. * * @return The list passed. + * + * @deprecated This function will be removed in 3.0.0. You shouldn't be using it anyway. */ GList *purple_conv_chat_set_users(PurpleConvChat *chat, GList *users);