/* * How this works. * * Well, first off, the code recursively descends into the trie * until it finds the terminating letter of the command being removed. * Once it has done that, it marks the msg pointer as NULL then * reduces the reference count on that allocated struct MessageTree * since a command counts as a reference. * * Then it pops up the recurse stack. As it comes back up the recurse * The code checks to see if the child now has no pointers or msg * i.e. the links count has gone to zero. If it's no longer used, the * child struct MessageTree can be deleted. The parent reference * to this child is then removed and the parents link count goes down. * Thus, we continue to go back up removing all unused MessageTree(s) */ static void del_msg_element(struct MessageTree *mtree_p, const char *cmd) { struct MessageTree *ntree_p = NULL; /* * In case this is called for a nonexistent command * check that there is a msg pointer here, else links-- goes -ve * -db */ if (*cmd == '\0' && mtree_p->msg) { mtree_p->msg = NULL; mtree_p->links--; } else { if ((ntree_p = mtree_p->pointers[*cmd & (MAXPTRLEN - 1)])) { del_msg_element(ntree_p, cmd + 1); if (ntree_p->links == 0) { mtree_p->pointers[*cmd & (MAXPTRLEN - 1)] = NULL; mtree_p->links--; xfree(ntree_p); } } } }
/* mod_del_cmd() * * inputs - pointer to struct Message * output - none * side effects - unload this one command name */ void mod_del_cmd(struct Message *msg) { assert(msg); assert(msg->cmd); if (msg_tree_parse(msg->cmd)) del_msg_element(&msg_tree, msg->cmd); }
/* mod_del_cmd() * * inputs - pointer to struct Message * output - none * side effects - unload this one command name */ void mod_del_cmd(struct Message *msg) { assert(msg != NULL); if (msg == NULL) return; del_msg_element(&msg_tree, msg->cmd); }
/** Removes a service mapping. * @param[in] map Service mapping to remove. * @return Non-zero on success; zero if no command used the name. */ int unregister_mapping(struct s_map *map) { if (!msg_tree_parse(map->command, &msg_tree)) { /* This simply should never happen. */ assert(0); return 0; } del_msg_element(&msg_tree, map->msg->cmd); map->msg->extra = NULL; MyFree(map->msg); map->msg = NULL; return 1; }
/** Remove a message from the lookup trie. * @param[in,out] mtree_p Trie node to remove command from. * @param[in] cmd Text of command to remove. */ struct MessageTree * del_msg_element(struct MessageTree *mtree_p, char *cmd) { int slot = *cmd & (MAXPTRLEN-1); /* Either remove leaf message or from appropriate child. */ if (*cmd == '\0') mtree_p->msg = NULL; else mtree_p->pointers[slot] = del_msg_element(mtree_p->pointers[slot], cmd + 1); /* If current message or any child still exists, keep this node. */ if (mtree_p->msg) return mtree_p; for (slot = 0; slot < MAXPTRLEN; ++slot) if (mtree_p->pointers[slot]) return mtree_p; /* Otherwise, if we're not a root node, free it and return null. */ if (mtree_p != &msg_tree && mtree_p != &tok_tree) MyFree(mtree_p); return NULL; }