diff options
-rw-r--r-- | gatchat/gatchat.c | 110 |
1 files changed, 64 insertions, 46 deletions
diff --git a/gatchat/gatchat.c b/gatchat/gatchat.c index cfe21887..e69cd4e2 100644 --- a/gatchat/gatchat.c +++ b/gatchat/gatchat.c @@ -63,6 +63,9 @@ struct at_notify_node { GDestroyNotify notify; }; +typedef gboolean (*node_remove_func)(struct at_notify_node *node, + gpointer user_data); + struct at_notify { GSList *nodes; gboolean pdu; @@ -154,6 +157,57 @@ static gint at_command_compare_by_id(gconstpointer a, gconstpointer b) return 0; } +static gboolean at_chat_unregister_all(struct at_chat *chat, + node_remove_func func, + gpointer userdata) +{ + GHashTableIter iter; + struct at_notify *notify; + struct at_notify_node *node; + gpointer key, value; + GSList *p; + GSList *c; + GSList *t; + + if (chat->notify_list == NULL) + return FALSE; + + g_hash_table_iter_init(&iter, chat->notify_list); + + while (g_hash_table_iter_next(&iter, &key, &value)) { + notify = value; + + p = NULL; + c = notify->nodes; + + while (c) { + node = c->data; + + if (func(node, userdata) != TRUE) { + p = c; + c = c->next; + continue; + } + + if (p) + p->next = c->next; + else + notify->nodes = c->next; + + at_notify_node_destroy(node, NULL); + + t = c; + c = c->next; + g_slist_free_1(t); + } + + if (notify->nodes == NULL) + g_hash_table_iter_remove(&iter); + } + + return TRUE; +} + static struct at_command *at_command_create(guint gid, const char *cmd, const char **prefix_list, gboolean expect_pdu, @@ -1099,53 +1153,15 @@ static gboolean at_chat_unregister(struct at_chat *chat, guint group, guint id) return FALSE; } -static gboolean at_chat_unregister_group(struct at_chat *chat, guint group) +static gboolean node_compare_by_group(struct at_notify_node *node, + gpointer userdata) { - GHashTableIter iter; - struct at_notify *notify; - struct at_notify_node *node; - gpointer key, value; - GSList *p; - GSList *c; - GSList *t; - - if (chat->notify_list == NULL) - return FALSE; - - g_hash_table_iter_init(&iter, chat->notify_list); - - while (g_hash_table_iter_next(&iter, &key, &value)) { - notify = value; - - p = NULL; - c = notify->nodes; - - while (c) { - node = c->data; + guint group = GPOINTER_TO_UINT(userdata); - if (node->gid != group) { - p = c; - c = c->next; - continue; - } - - if (p) - p->next = c->next; - else - notify->nodes = c->next; - - at_notify_node_destroy(node, NULL); - - t = c; - c = c->next; - g_slist_free_1(t); - } - - if (notify->nodes == NULL) - g_hash_table_iter_remove(&iter); - } + if (node->gid == group) + return TRUE; - return TRUE; + return FALSE; } static struct at_chat *create_chat(GIOChannel *channel, GIOFlags flags, @@ -1310,7 +1326,7 @@ void g_at_chat_unref(GAtChat *chat) return; at_chat_cancel_group(chat->parent, chat->group); - at_chat_unregister_group(chat->parent, chat->group); + g_at_chat_unregister_all(chat); at_chat_unref(chat->parent); g_free(chat); @@ -1431,5 +1447,7 @@ gboolean g_at_chat_unregister_all(GAtChat *chat) if (chat == NULL) return FALSE; - return at_chat_unregister_group(chat->parent, chat->group); + return at_chat_unregister_all(chat->parent, + node_compare_by_group, + GUINT_TO_POINTER(chat->group)); } |