pidgin: b3ac8324: Add purple_{buddy,chat,group,contact}_de...

elb at pidgin.im elb at pidgin.im
Thu Apr 9 14:10:45 EDT 2009


-----------------------------------------------------------------
Revision: b3ac8324be2c3d155c50216ff7522ec7319984b1
Ancestor: 3c568b43fb4447b65a2b06e6767340edd7763c53
Author: hebnern at gmail.com
Date: 2009-04-09T17:33:20
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/b3ac8324be2c3d155c50216ff7522ec7319984b1

Modified files:
        ChangeLog ChangeLog.API libpurple/blist.c libpurple/blist.h

ChangeLog: 

Add purple_{buddy,chat,group,contact}_destroy to the blist API, free
blist data on libpurple unload.  Thanks to Nick Hebner for this.

References #8683

-------------- next part --------------
============================================================
--- ChangeLog	0d73d8f31689920d271ad056dad78384aba1a429
+++ ChangeLog	b899615cdebcbb5504177c480a4281bf62742fea
@@ -9,6 +9,9 @@ version 2.6.0 (??/??/2009):
 	* Removed the unmaintained and unneeded toc protocol plugin.
 	* Fixed NTLM authentication on big-endian systems.
 
+	libpurple:
+	* Various memory cleanups when unloading libpurple. (Nick Hebner)
+
 	XMPP:
 	* Add voice & video support with Jingle (XEP-0166, 0167, 0176, & 0177),
 	  and voice support with GTalk and GMail. (Mike "Maiku" Ruprecht)
============================================================
--- ChangeLog.API	c4516b9a52728841169223a990807bebf1942b0c
+++ ChangeLog.API	bec918fce75f383e5e5c0a38ed5b7cc48cc9457b
@@ -9,6 +9,7 @@ version 2.6.0 (??/??/2009):
 		* PURPLE_CONTACT
 		* PURPLE_BUDDY
 		* PURPLE_CHAT
+		* purple_buddy_destroy
 		* purple_buddy_get_protocol_data
 		* purple_buddy_set_protocol_data
 		* purple_buddy_get_local_buddy_alias
@@ -17,9 +18,12 @@ version 2.6.0 (??/??/2009):
 		* purple_blist_set_ui_data
 		* purple_blist_node_get_ui_data
 		* purple_blist_node_set_ui_data
+		* purple_chat_destroy
 		* purple_connection_get_protocol_data
 		* purple_connection_set_protocol_data
+		* purple_contact_destroy
 		* purple_global_proxy_set_info
+		* purple_group_destroy
 		* purple_log_get_activity_score
 		* purple_network_force_online
 		* purple_network_set_stun_server
============================================================
--- libpurple/blist.c	ba2294dc081c1a8f1d5ba8bfd5d19768869d90f1
+++ libpurple/blist.c	11e434ee9e713dc54b4f5affb7e5e6d1e03a8750
@@ -1202,6 +1202,16 @@ PurpleChat *purple_chat_new(PurpleAccoun
 	return chat;
 }
 
+void
+purple_chat_destroy(PurpleChat *chat)
+{
+	g_hash_table_destroy(chat->components);
+	g_hash_table_destroy(chat->node.settings);
+	g_free(chat->alias);
+	PURPLE_DBUS_UNREGISTER_POINTER(chat);
+	g_free(chat);
+}
+
 PurpleBuddy *purple_buddy_new(PurpleAccount *account, const char *name, const char *alias)
 {
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
@@ -1229,6 +1239,40 @@ void
 }
 
 void
+purple_buddy_destroy(PurpleBuddy *buddy)
+{
+	PurplePlugin *prpl;
+	PurplePluginProtocolInfo *prpl_info;
+
+	/*
+	 * Tell the owner PRPL that we're about to free the buddy so it
+	 * can free proto_data
+	 */
+	prpl = purple_find_prpl(purple_account_get_protocol_id(buddy->account));
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+	if (prpl_info && prpl_info->buddy_free)
+		prpl_info->buddy_free(buddy);
+
+	/* Delete the node */
+	purple_buddy_icon_unref(buddy->icon);
+	g_hash_table_destroy(buddy->node.settings);
+	purple_presence_destroy(buddy->presence);
+	g_free(buddy->name);
+	g_free(buddy->alias);
+	g_free(buddy->server_alias);
+
+	PURPLE_DBUS_UNREGISTER_POINTER(buddy);
+	g_free(buddy);
+
+	/* FIXME: Once PurpleBuddy is a GObject, timeout callbacks can
+	 * g_object_ref() it when connecting the callback and
+	 * g_object_unref() it in the handler.  That way, it won't
+	 * get freed while the timeout is pending and this line can
+	 * be removed. */
+	while (g_source_remove_by_user_data((gpointer *)buddy));
+}
+
+void
 purple_buddy_set_icon(PurpleBuddy *buddy, PurpleBuddyIcon *icon)
 {
 	g_return_if_fail(buddy != NULL);
@@ -1519,6 +1563,14 @@ PurpleContact *purple_contact_new()
 	return contact;
 }
 
+void
+purple_contact_destroy(PurpleContact *contact)
+{
+	g_hash_table_destroy(contact->node.settings);
+	PURPLE_DBUS_UNREGISTER_POINTER(contact);
+	g_free(contact);
+}
+
 void purple_contact_set_alias(PurpleContact *contact, const char *alias)
 {
 	purple_blist_alias_contact(contact,alias);
@@ -1588,6 +1640,15 @@ PurpleGroup *purple_group_new(const char
 	return group;
 }
 
+void
+purple_group_destroy(PurpleGroup *group)
+{
+	g_hash_table_destroy(group->node.settings);
+	g_free(group->name);
+	PURPLE_DBUS_UNREGISTER_POINTER(group);
+	g_free(group);
+}
+
 void purple_blist_add_contact(PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node)
 {
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
@@ -1848,9 +1909,7 @@ void purple_blist_remove_contact(PurpleC
 			ops->remove(purplebuddylist, node);
 
 		/* Delete the node */
-		g_hash_table_destroy(contact->node.settings);
-		PURPLE_DBUS_UNREGISTER_POINTER(contact);
-		g_free(contact);
+		purple_contact_destroy(contact);
 	}
 }
 
@@ -1861,8 +1920,6 @@ void purple_blist_remove_buddy(PurpleBud
 	PurpleContact *contact;
 	PurpleGroup *group;
 	struct _purple_hbuddy hb;
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info = NULL;
 
 	g_return_if_fail(buddy != NULL);
 
@@ -1918,34 +1975,8 @@ void purple_blist_remove_buddy(PurpleBud
 	/* Signal that the buddy has been removed before freeing the memory for it */
 	purple_signal_emit(purple_blist_get_handle(), "buddy-removed", buddy);
 
-	/*
-	 * Tell the owner PRPL that we're about to free the buddy so it
-	 * can free proto_data
-	 */
-	prpl = purple_find_prpl(purple_account_get_protocol_id(buddy->account));
-	if (prpl)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-	if (prpl_info && prpl_info->buddy_free)
-		prpl_info->buddy_free(buddy);
+	purple_buddy_destroy(buddy);
 
-	/* Delete the node */
-	purple_buddy_icon_unref(buddy->icon);
-	g_hash_table_destroy(buddy->node.settings);
-	purple_presence_destroy(buddy->presence);
-	g_free(buddy->name);
-	g_free(buddy->alias);
-	g_free(buddy->server_alias);
-
-	PURPLE_DBUS_UNREGISTER_POINTER(buddy);
-	g_free(buddy);
-
-	/* FIXME: Once PurpleBuddy is a GObject, timeout callbacks can
-	 * g_object_ref() it when connecting the callback and
-	 * g_object_unref() it in the handler.  That way, it won't
-	 * get freed while the timeout is pending and this line can
-	 * be removed. */
-	while (g_source_remove_by_user_data((gpointer *)buddy));
-
 	/* If the contact is empty then remove it */
 	if ((contact != NULL) && !cnode->child)
 		purple_blist_remove_contact(contact);
@@ -1988,11 +2019,7 @@ void purple_blist_remove_chat(PurpleChat
 		ops->remove(purplebuddylist, node);
 
 	/* Delete the node */
-	g_hash_table_destroy(chat->components);
-	g_hash_table_destroy(chat->node.settings);
-	g_free(chat->alias);
-	PURPLE_DBUS_UNREGISTER_POINTER(chat);
-	g_free(chat);
+	purple_chat_destroy(chat);
 }
 
 void purple_blist_remove_group(PurpleGroup *group)
@@ -2033,10 +2060,7 @@ void purple_blist_remove_group(PurpleGro
 	}
 
 	/* Delete the node */
-	g_hash_table_destroy(group->node.settings);
-	g_free(group->name);
-	PURPLE_DBUS_UNREGISTER_POINTER(group);
-	g_free(group);
+	purple_group_destroy(group);
 }
 
 PurpleBuddy *purple_contact_get_priority_buddy(PurpleContact *contact)
@@ -2587,6 +2611,28 @@ static void
 }
 
 static void
+purple_blist_node_destroy(PurpleBlistNode *node)
+{
+	PurpleBlistNode *child, *next_child;
+  
+	child = node->child;
+	while (child) {
+		next_child = child->next;
+		purple_blist_node_destroy(child);
+		child = next_child;
+	}
+
+	if (PURPLE_BLIST_NODE_IS_BUDDY(node))
+		purple_buddy_destroy((PurpleBuddy*)node);
+	else if (PURPLE_BLIST_NODE_IS_CHAT(node))
+		purple_chat_destroy((PurpleChat*)node);
+	else if (PURPLE_BLIST_NODE_IS_CONTACT(node))
+		purple_contact_destroy((PurpleContact*)node);
+	else if (PURPLE_BLIST_NODE_IS_GROUP(node))
+		purple_group_destroy((PurpleGroup*)node);
+}
+
+static void
 purple_blist_node_setting_free(gpointer data)
 {
 	PurpleValue *value;
@@ -2874,12 +2920,20 @@ purple_blist_uninit(void)
 void
 purple_blist_uninit(void)
 {
-	if (save_timer != 0)
-	{
+	PurpleBlistNode *node, *next_node;
+
+	if (save_timer != 0) {
 		purple_timeout_remove(save_timer);
 		save_timer = 0;
 		purple_blist_sync();
 	}
 
+	node = purple_blist_get_root();
+	while (node) {
+		next_node = node->next;
+		purple_blist_node_destroy(node);
+		node = next_node;
+	}
+
 	purple_signals_unregister_by_instance(purple_blist_get_handle());
 }
============================================================
--- libpurple/blist.h	93ef934fff7f894ba39a2024fdac4a77c86c49c2
+++ libpurple/blist.h	b1d8652bb542bc432a48db33454250a44b26b797
@@ -478,6 +478,13 @@ PurpleChat *purple_chat_new(PurpleAccoun
 PurpleChat *purple_chat_new(PurpleAccount *account, const char *alias, GHashTable *components);
 
 /**
+ * Destroys a chat
+ *
+ * @param chat       The chat to destroy
+ */
+void purple_chat_destroy(PurpleChat *chat);
+
+/**
  * Adds a new chat to the buddy list.
  *
  * The chat will be inserted right after node or appended to the end
@@ -501,6 +508,13 @@ PurpleBuddy *purple_buddy_new(PurpleAcco
 PurpleBuddy *purple_buddy_new(PurpleAccount *account, const char *name, const char *alias);
 
 /**
+ * Destroys a buddy
+ *
+ * @param buddy     The buddy to destroy
+ */
+void purple_buddy_destroy(PurpleBuddy *buddy);
+
+/**
  * Sets a buddy's icon.
  *
  * This should only be called from within Purple. You probably want to
@@ -611,6 +625,13 @@ PurpleGroup *purple_group_new(const char
 PurpleGroup *purple_group_new(const char *name);
 
 /**
+ * Destroys a group
+ *
+ * @param group  The group to destroy
+*/
+void purple_group_destroy(PurpleGroup *group);
+
+/**
  * Adds a new group to the buddy list.
  *
  * The new group will be inserted after insert or prepended to the list if
@@ -629,6 +650,13 @@ PurpleContact *purple_contact_new(void);
 PurpleContact *purple_contact_new(void);
 
 /**
+ * Destroys a contact
+ *
+ * @param contact  The contact to destroy
+ */
+void purple_contact_destroy(PurpleContact *contact);
+
+/**
  * Adds a new contact to the buddy list.
  *
  * The new contact will be inserted after insert or prepended to the list if


More information about the Commits mailing list