最近对原有代码进行整理、优化、重构,其中对命令解析执行的函数,通常会采用switch case的方式找到命令,然后解析参数,最后执行,如果所有都放到一个函数中,
将会导致该函数的空间复杂都过高。以下是一种一维表驱动的方式重构优化这类问题的方式,在此举例。
后记:但是如果每个命令下又有一级,甚至多级子命令,又将导致此类问题的重现,所以需要将这一组件通用化,可以递归重用。后续如果有更好的方式,将在此继续更新。
typedef int (*para_parse)(int argc, char **args,void *para_out); typedef int (*doexe)(void *para); typedef struct cmd_node { const char *name; unsigned int para_len; para_parse getopt; doexe exe; }cmd_node_t; typedef struct conn_para{ unsigned char essid[MAX_SSID_LEN]; unsigned char password[MAX_KEY_LEN]; }conn_para_t; int __conn_getopt(int argc, char **args,void *para_out); int __conn_exe(void *para); cmd_node_t cmd_tbl[] = { {"conn", sizeof(conn_para_t), __conn_getopt, __conn_exe}, {"disconn", sizeof(conn_para_t), __conn_getopt, __conn_exe}, {"status", sizeof(conn_para_t), __conn_getopt, __conn_exe}, }; int __conn_getopt(int argc, char **args, void *para_out) { conn_para_t *para = (conn_para_t *)para_out; if (argc != 2 && argc != 3) { ak_print_normal("%s",help_sta[1]); return; } if(strlen(args[1]) > MAX_SSID_LEN) { ak_print_normal("ssid should less than 32 characters "); return; } if(argc == 3 && strlen(args[2]) > MAX_KEY_LEN) { ak_print_normal("password should less than 64 characters "); return; } strcpy(para->essid, args[1]); if(argc == 3) { strcpy(para->password, args[2]); } else { memset(para->password, 0, MAX_KEY_LEN); } } int __conn_exe(void *para) { /*create a task to connetc AP, so the STA can reconnect AP case the AP unavailable temporily for some reason*/ if(g_sta_conn_thread_id == AK_INVALID_TASK) { wifi_set_mode(WIFI_MODE_STA); sta_reconn_flag = AK_TRUE; ak_thread_create(&g_sta_conn_thread_id , (void*)sta_conn_thread , para, 4096, 10); } else { ak_print_normal("sta is connecting, please disconnect it first "); } } int find_cmd(char *name) { int i; int size = sizeof(cmd_tbl)/sizeof(cmd_node_t); for(i = 0; i < size; i++) { if(!strcmp(name,cmd_tbl[i].name)) { break; } } if(i >= size) { return -1; } return i; } static void cmd_wifi_sta_new(int argc, char **args) { int index = find_cmd(args[0]); cmd_node_t *node = &cmd_tbl[index]; if(index < 0) { ak_print_error("find cmd fail "); return; } void *para = malloc(node->para_len); node->getopt(argc-1,&args[1],para); node->exe(para); free(para);
}