Add r_cmd_desc_remove API to unregister commands (#17349)

This commit is contained in:
Riccardo Schirone 2020-07-24 08:23:56 +02:00 committed by GitHub
parent 1c74f3f729
commit 652df7f497
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 71 additions and 14 deletions

View File

@ -30,6 +30,34 @@ static bool cmd_desc_set_parent(RCmdDesc *cd, RCmdDesc *parent) {
return true;
}
static void cmd_desc_unset_parent(RCmdDesc *cd) {
r_return_if_fail (cd && cd->parent);
RCmdDesc *parent = cd->parent;
r_pvector_remove_data (&parent->children, cd);
parent->n_children--;
cd->parent = NULL;
}
static void cmd_desc_remove_from_ht_cmds(RCmd *cmd, RCmdDesc *cd) {
void **it_cd;
bool res = ht_pp_delete (cmd->ht_cmds, cd->name);
r_return_if_fail (res);
r_cmd_desc_children_foreach (cd, it_cd) {
RCmdDesc *child_cd = *it_cd;
cmd_desc_remove_from_ht_cmds (cmd, child_cd);
}
}
static void cmd_desc_free(RCmdDesc *cd) {
if (!cd) {
return;
}
r_pvector_clear (&cd->children);
free (cd->name);
free (cd);
}
static RCmdDesc *create_cmd_desc(RCmd *cmd, RCmdDesc *parent, RCmdDescType type, const char *name, const RCmdDescHelp *help) {
RCmdDesc *res = R_NEW0 (RCmdDesc);
if (!res) {
@ -42,14 +70,14 @@ static RCmdDesc *create_cmd_desc(RCmd *cmd, RCmdDesc *parent, RCmdDescType type,
}
res->n_children = 0;
res->help = help? help: &not_defined_help;
r_pvector_init (&res->children, (RPVectorFree)r_cmd_desc_free);
r_pvector_init (&res->children, (RPVectorFree)cmd_desc_free);
if (!ht_pp_insert (cmd->ht_cmds, name, res)) {
goto err;
}
cmd_desc_set_parent (res, parent);
return res;
err:
r_cmd_desc_free (res);
cmd_desc_free (res);
return NULL;
}
@ -97,7 +125,7 @@ R_API RCmd *r_cmd_free(RCmd *cmd) {
R_FREE (cmd->cmds[i]);
}
}
r_cmd_desc_free (cmd->root_cmd_desc);
cmd_desc_free (cmd->root_cmd_desc);
free (cmd);
return NULL;
}
@ -1132,17 +1160,17 @@ R_API RCmdDesc *r_cmd_desc_oldinput_new(RCmd *cmd, RCmdDesc *parent, const char
return res;
}
R_API void r_cmd_desc_free(RCmdDesc *cd) {
if (!cd) {
return;
}
r_pvector_clear (&cd->children);
free (cd->name);
free (cd);
}
R_API RCmdDesc *r_cmd_desc_parent(RCmdDesc *cd) {
r_return_val_if_fail (cd, NULL);
return cd->parent;
}
R_API bool r_cmd_desc_remove(RCmd *cmd, RCmdDesc *cd) {
r_return_val_if_fail (cmd && cd, false);
if (cd->parent) {
cmd_desc_unset_parent (cd);
}
cmd_desc_remove_from_ht_cmds (cmd, cd);
cmd_desc_free (cd);
return true;
}

View File

@ -167,8 +167,8 @@ R_API char *r_cmd_get_help(RCmd *cmd, RCmdParsedArgs *args, bool use_color);
/* RCmdDescriptor */
R_API RCmdDesc *r_cmd_desc_argv_new(RCmd *cmd, RCmdDesc *parent, const char *name, RCmdArgvCb cb, const RCmdDescHelp *help);
R_API RCmdDesc *r_cmd_desc_oldinput_new(RCmd *cmd, RCmdDesc *parent, const char *name, RCmdCb cb, const RCmdDescHelp *help);
R_API void r_cmd_desc_free(RCmdDesc *cd);
R_API RCmdDesc *r_cmd_desc_parent(RCmdDesc *cd);
R_API bool r_cmd_desc_remove(RCmd *cmd, RCmdDesc *cd);
#define r_cmd_desc_children_foreach(root, it_cd) r_pvector_foreach (&root->children, it_cd)

View File

@ -385,6 +385,34 @@ bool test_cmd_oldinput_help(void) {
mu_end;
}
bool test_remove_cmd(void) {
RCmd *cmd = r_cmd_new ();
RCmdDesc *root = r_cmd_get_root (cmd);
RCmdDesc *x_cd = r_cmd_desc_argv_new (cmd, root, "x", NULL, NULL);
RCmdDesc *p_cd = r_cmd_desc_argv_new (cmd, root, "p", NULL, NULL);
RCmdDesc *pd_cd = r_cmd_desc_argv_new (cmd, p_cd, "pd", pd_handler, NULL);
r_cmd_desc_argv_new (cmd, p_cd, "px", pd_handler, NULL);
mu_assert_ptreq (r_cmd_get_desc (cmd, "x"), x_cd, "x is found");
mu_assert_ptreq (r_cmd_get_desc (cmd, "pd"), pd_cd, "pd is found");
mu_assert_eq (root->n_children, 2, "root has 2 commands as children");
r_cmd_desc_remove (cmd, p_cd);
mu_assert_eq (root->n_children, 1, "p was removed, now root has 1 command as children");
mu_assert_null (r_cmd_get_desc (cmd, "p"), "p should not be found anymore");
mu_assert_null (r_cmd_get_desc (cmd, "pd"), "pd should not be found anymore");
mu_assert_null (r_cmd_get_desc (cmd, "px"), "px should not be found anymore");
void **it_cd;
r_cmd_desc_children_foreach (root, it_cd) {
RCmdDesc *cd = *it_cd;
mu_assert_ptrneq (cd, p_cd, "p should not be found anymore");
}
r_cmd_free (cmd);
r_cons_free ();
mu_end;
}
int all_tests() {
mu_run_test (test_parsed_args_noargs);
mu_run_test (test_parsed_args_onearg);
@ -401,6 +429,7 @@ int all_tests() {
mu_run_test (test_cmd_help);
mu_run_test (test_cmd_group_help);
mu_run_test (test_cmd_oldinput_help);
mu_run_test (test_remove_cmd);
return tests_passed != tests_run;
}