Mercurial > pidgin.yaz
diff libpurple/blist.c @ 27998:31905a0d1c9d
merge of '6f4d0e183ebb11a95980e184e63bd4709aa24306'
and '9fa808b57669d76c0989b16c2568cb7a7047511e'
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Wed, 22 Jul 2009 06:12:13 +0000 |
parents | 429fce11f244 |
children | 14ce47859540 |
line wrap: on
line diff
--- a/libpurple/blist.c Wed Jul 22 06:10:17 2009 +0000 +++ b/libpurple/blist.c Wed Jul 22 06:12:13 2009 +0000 @@ -48,6 +48,12 @@ */ static GHashTable *buddies_cache = NULL; +/** + * A hash table used for efficient lookups of groups by name. + * UTF-8 collate-key => PurpleGroup*. + */ +static GHashTable *groups_cache = NULL; + static guint save_timer = 0; static gboolean blist_loaded = FALSE; @@ -83,14 +89,18 @@ PurpleBlistNode *group; }; +/* This function must not use purple_normalize */ static guint _purple_blist_hbuddy_hash(struct _purple_hbuddy *hb) { - return g_str_hash(hb->name); + return g_str_hash(hb->name) ^ g_direct_hash(hb->group) ^ g_direct_hash(hb->account); } +/* This function must not use purple_normalize */ static guint _purple_blist_hbuddy_equal(struct _purple_hbuddy *hb1, struct _purple_hbuddy *hb2) { - return (purple_strequal(hb1->name, hb2->name) && hb1->account == hb2->account && hb1->group == hb2->group); + return (hb1->group == hb2->group && + hb1->account == hb2->account && + g_str_equal(hb1->name, hb2->name)); } static void _purple_blist_hbuddy_free_key(struct _purple_hbuddy *hb) @@ -702,6 +712,10 @@ buddies_cache = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)g_hash_table_destroy); + groups_cache = g_hash_table_new_full((GHashFunc)g_str_hash, + (GEqualFunc)g_str_equal, + (GDestroyNotify)g_free, NULL); + for (account = purple_accounts_get_all(); account != NULL; account = account->next) { purple_blist_buddies_cache_add_account(account->data); @@ -936,15 +950,14 @@ g_return_if_fail(buddy != NULL); hb = g_new(struct _purple_hbuddy, 1); - hb->name = g_strdup(purple_normalize(buddy->account, buddy->name)); + hb->name = (gchar *)purple_normalize(buddy->account, buddy->name); hb->account = buddy->account; hb->group = ((PurpleBlistNode *)buddy)->parent->parent; g_hash_table_remove(purplebuddylist->buddies, hb); - + account_buddies = g_hash_table_lookup(buddies_cache, buddy->account); g_hash_table_remove(account_buddies, hb); - g_free(hb->name); hb->name = g_strdup(purple_normalize(buddy->account, name)); g_hash_table_replace(purplebuddylist->buddies, hb, buddy); @@ -1201,6 +1214,7 @@ } else { /* A simple rename */ PurpleBlistNode *cnode, *bnode; + gchar* key; /* Build a GList of all buddies in this group */ for (cnode = ((PurpleBlistNode *)source)->child; cnode != NULL; cnode = cnode->next) { @@ -1211,6 +1225,13 @@ old_name = source->name; source->name = new_name; + + key = g_utf8_collate_key(old_name, -1); + g_hash_table_remove(groups_cache, key); + g_free(key); + + key = g_utf8_collate_key(new_name, -1); + g_hash_table_insert(groups_cache, key, source); } /* Save our changes */ @@ -1278,8 +1299,8 @@ PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); PurpleChat *chat; - g_return_val_if_fail(account != NULL, FALSE); - g_return_val_if_fail(components != NULL, FALSE); + g_return_val_if_fail(account != NULL, NULL); + g_return_val_if_fail(components != NULL, NULL); chat = g_new0(PurpleChat, 1); chat->account = account; @@ -1583,17 +1604,14 @@ purple_blist_schedule_save(); if (bnode->parent->parent != (PurpleBlistNode*)g) { - hb = g_new(struct _purple_hbuddy, 1); - hb->name = g_strdup(purple_normalize(buddy->account, buddy->name)); - hb->account = buddy->account; - hb->group = bnode->parent->parent; - g_hash_table_remove(purplebuddylist->buddies, hb); + struct _purple_hbuddy hb; + hb.name = (gchar *)purple_normalize(buddy->account, buddy->name); + hb.account = buddy->account; + hb.group = bnode->parent->parent; + g_hash_table_remove(purplebuddylist->buddies, &hb); account_buddies = g_hash_table_lookup(buddies_cache, buddy->account); - g_hash_table_remove(account_buddies, hb); - - g_free(hb->name); - g_free(hb); + g_hash_table_remove(account_buddies, &hb); } if (!bnode->parent->child) { @@ -1811,7 +1829,7 @@ GHashTable *account_buddies; struct _purple_hbuddy *hb, *hb2; - + hb = g_new(struct _purple_hbuddy, 1); hb->name = g_strdup(purple_normalize(b->account, b->name)); hb->account = b->account; @@ -1944,6 +1962,7 @@ { PurpleBlistUiOps *ops; PurpleBlistNode *gnode = (PurpleBlistNode*)group; + gchar* key; g_return_if_fail(group != NULL); g_return_if_fail(PURPLE_BLIST_NODE_IS_GROUP((PurpleBlistNode *)group)); @@ -1952,6 +1971,9 @@ if (!purplebuddylist->root) { purplebuddylist->root = gnode; + + key = g_utf8_collate_key(group->name, -1); + g_hash_table_insert(groups_cache, key, group); return; } @@ -1971,6 +1993,9 @@ gnode->prev->next = gnode->next; if (gnode->next) gnode->next->prev = gnode->prev; + } else { + key = g_utf8_collate_key(group->name, -1); + g_hash_table_insert(groups_cache, key, group); } if (node && PURPLE_BLIST_NODE_IS_GROUP(node)) { @@ -2097,7 +2122,7 @@ purple_blist_schedule_save(); /* Remove this buddy from the buddies hash table */ - hb.name = g_strdup(purple_normalize(buddy->account, buddy->name)); + hb.name = (gchar *)purple_normalize(buddy->account, buddy->name); hb.account = buddy->account; hb.group = gnode; g_hash_table_remove(purplebuddylist->buddies, &hb); @@ -2105,8 +2130,6 @@ account_buddies = g_hash_table_lookup(buddies_cache, buddy->account); g_hash_table_remove(account_buddies, &hb); - g_free(hb.name); - /* Update the UI */ if (ops && ops->remove) ops->remove(purplebuddylist, node); @@ -2172,6 +2195,7 @@ PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); PurpleBlistNode *node; GList *l; + gchar* key; g_return_if_fail(group != NULL); @@ -2189,6 +2213,10 @@ if (node->next) node->next->prev = node->prev; + key = g_utf8_collate_key(group->name, -1); + g_hash_table_remove(groups_cache, key); + g_free(key); + purple_blist_schedule_save(); /* Update the UI */ @@ -2352,16 +2380,14 @@ g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL); hb.account = account; - hb.name = g_strdup(purple_normalize(account, name)); + hb.name = (gchar *)purple_normalize(account, name); for (group = purplebuddylist->root; group; group = group->next) { hb.group = group; if ((buddy = g_hash_table_lookup(purplebuddylist->buddies, &hb))) { - g_free(hb.name); return buddy; } } - g_free(hb.name); return NULL; } @@ -2370,20 +2396,16 @@ PurpleGroup *group) { struct _purple_hbuddy hb; - PurpleBuddy *ret; g_return_val_if_fail(purplebuddylist != NULL, NULL); g_return_val_if_fail(account != NULL, NULL); g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL); - hb.name = g_strdup(purple_normalize(account, name)); + hb.name = (gchar *)purple_normalize(account, name); hb.account = account; hb.group = (PurpleBlistNode*)group; - ret = g_hash_table_lookup(purplebuddylist->buddies, &hb); - g_free(hb.name); - - return ret; + return g_hash_table_lookup(purplebuddylist->buddies, &hb); } static void find_acct_buddies(gpointer key, gpointer value, gpointer data) @@ -2406,7 +2428,7 @@ if ((name != NULL) && (*name != '\0')) { struct _purple_hbuddy hb; - hb.name = g_strdup(purple_normalize(account, name)); + hb.name = (gchar *)purple_normalize(account, name); hb.account = account; for (node = purplebuddylist->root; node != NULL; node = node->next) { @@ -2414,7 +2436,6 @@ if ((buddy = g_hash_table_lookup(purplebuddylist->buddies, &hb)) != NULL) ret = g_slist_prepend(ret, buddy); } - g_free(hb.name); } else { GSList *list = NULL; GHashTable *buddies = g_hash_table_lookup(buddies_cache, account); @@ -2427,17 +2448,17 @@ PurpleGroup *purple_find_group(const char *name) { - PurpleBlistNode *node; + gchar* key; + PurpleGroup *group; g_return_val_if_fail(purplebuddylist != NULL, NULL); g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL); - for (node = purplebuddylist->root; node != NULL; node = node->next) { - if (!purple_utf8_strcasecmp(((PurpleGroup *)node)->name, name)) - return (PurpleGroup *)node; - } - - return NULL; + key = g_utf8_collate_key(name, -1); + group = g_hash_table_lookup(groups_cache, key); + g_free(key); + + return group; } PurpleChat * @@ -3105,6 +3126,8 @@ purple_blist_sync(); } + purple_blist_destroy(); + node = purple_blist_get_root(); while (node) { next_node = node->next; @@ -3112,9 +3135,17 @@ node = next_node; } purplebuddylist->root = NULL; - + g_hash_table_destroy(purplebuddylist->buddies); g_hash_table_destroy(buddies_cache); + g_hash_table_destroy(groups_cache); + + buddies_cache = NULL; + groups_cache = NULL; + + PURPLE_DBUS_UNREGISTER_POINTER(purplebuddylist); + g_free(purplebuddylist); + purplebuddylist = NULL; purple_signals_disconnect_by_handle(purple_blist_get_handle()); purple_signals_unregister_by_instance(purple_blist_get_handle());