Skip to content

Commit

Permalink
fix: add context to command handler callback
Browse files Browse the repository at this point in the history
The current design does not allow passing user-defined data to the
command handler callback, which makes it difficult to shared data
between the main program and callbacks.

In this patch, we introduce an API change, which may break the code that
use the sub-command mechanism. However, since the sub-command API has
not been publicly introduced, we hope this necessary change will not
have big impact to users.
  • Loading branch information
tomghuang committed Nov 17, 2024
1 parent 85ddd57 commit 8ddd0bc
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 7 deletions.
5 changes: 3 additions & 2 deletions src/arg_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ void arg_cmd_uninit(void) {
arg_hashtable_destroy(s_hashtable, 1);
}

void arg_cmd_register(const char* name, arg_cmdfn* proc, const char* description) {
void arg_cmd_register(const char* name, arg_cmdfn* proc, const char* description, void* ctx) {
arg_cmd_info_t* cmd_info;
size_t slen_name;
void* k;
Expand Down Expand Up @@ -158,6 +158,7 @@ void arg_cmd_register(const char* name, arg_cmdfn* proc, const char* description
#endif

cmd_info->proc = proc;
cmd_info->ctx = ctx;

slen_name = strlen(name);
k = xmalloc(slen_name + 1);
Expand All @@ -182,7 +183,7 @@ int arg_cmd_dispatch(const char* name, int argc, char* argv[], arg_dstr_t res) {
assert(cmd_info != NULL);
assert(cmd_info->proc != NULL);

return cmd_info->proc(argc, argv, res);
return cmd_info->proc(argc, argv, res, cmd_info->ctx);
}

arg_cmd_info_t* arg_cmd_info(const char* name) {
Expand Down
5 changes: 3 additions & 2 deletions src/argtable3.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ typedef int(arg_scanfn)(void* parent, const char* argval);
typedef int(arg_checkfn)(void* parent);
typedef void(arg_errorfn)(void* parent, arg_dstr_t ds, int error, const char* argval, const char* progname);
typedef void(arg_dstr_freefn)(char* buf);
typedef int(arg_cmdfn)(int argc, char* argv[], arg_dstr_t res);
typedef int(arg_cmdfn)(int argc, char* argv[], arg_dstr_t res, void* ctx);
typedef int(arg_comparefn)(const void* k1, const void* k2);

/**
Expand Down Expand Up @@ -210,6 +210,7 @@ typedef struct arg_cmd_info {
char name[ARG_CMD_NAME_LEN]; /**< Sub-command name */
char description[ARG_CMD_DESCRIPTION_LEN]; /**< A short description */
arg_cmdfn* proc; /**< Sub-command procedure */
void* ctx; /**< Sub-command context */
} arg_cmd_info_t;

/**** arg_xxx constructor functions *********************************/
Expand Down Expand Up @@ -515,7 +516,7 @@ ARG_EXTERN char* arg_dstr_cstr(arg_dstr_t ds);

ARG_EXTERN void arg_cmd_init(void);
ARG_EXTERN void arg_cmd_uninit(void);
ARG_EXTERN void arg_cmd_register(const char* name, arg_cmdfn* proc, const char* description);
ARG_EXTERN void arg_cmd_register(const char* name, arg_cmdfn* proc, const char* description, void* ctx);
ARG_EXTERN void arg_cmd_unregister(const char* name);
ARG_EXTERN int arg_cmd_dispatch(const char* name, int argc, char* argv[], arg_dstr_t res);
ARG_EXTERN unsigned int arg_cmd_count(void);
Expand Down
6 changes: 3 additions & 3 deletions tests/testargcmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
#pragma warning(disable : 4204)
#endif

int cmd1_proc(int argc, char* argv[], arg_dstr_t res) {
int cmd1_proc(int argc, char* argv[], arg_dstr_t res, void* ctx) {
if (argc == 0) {
arg_dstr_catf(res, "cmd1 fail");
return 1;
Expand All @@ -54,8 +54,8 @@ int cmd1_proc(int argc, char* argv[], arg_dstr_t res) {
void test_argcmd_basic_001(CuTest* tc) {
arg_cmd_init();
CuAssertIntEquals(tc, 0, arg_cmd_count());
arg_cmd_register("cmd1", cmd1_proc, "description of cmd1");

arg_cmd_register("cmd1", cmd1_proc, "description of cmd1", NULL);
CuAssertIntEquals(tc, 1, arg_cmd_count());

char* argv[] = {
Expand Down

0 comments on commit 8ddd0bc

Please sign in to comment.