From 8ddd0bc1f0b95957625b6cc986ae8c003530c4b0 Mon Sep 17 00:00:00 2001 From: Tom Huang Date: Sun, 17 Nov 2024 07:49:41 -0800 Subject: [PATCH] fix: add context to command handler callback 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. --- src/arg_cmd.c | 5 +++-- src/argtable3.h | 5 +++-- tests/testargcmd.c | 6 +++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/arg_cmd.c b/src/arg_cmd.c index 455407e..a58e871 100644 --- a/src/arg_cmd.c +++ b/src/arg_cmd.c @@ -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; @@ -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); @@ -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) { diff --git a/src/argtable3.h b/src/argtable3.h index add3c85..8caa687 100644 --- a/src/argtable3.h +++ b/src/argtable3.h @@ -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); /** @@ -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 *********************************/ @@ -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); diff --git a/tests/testargcmd.c b/tests/testargcmd.c index d1942f9..872edaf 100644 --- a/tests/testargcmd.c +++ b/tests/testargcmd.c @@ -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; @@ -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[] = {