dev #2
							
								
								
									
										13
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								README.md
									
									
									
									
									
								
							@@ -92,9 +92,10 @@ example -h
 | 
			
		||||
 | 
			
		||||
1. 初始化解析器
 | 
			
		||||
```c
 | 
			
		||||
ArgParse *argParseInit(char *documentation);
 | 
			
		||||
ArgParse *argParseInit(char *documentation,ArgParseValueType value_type);
 | 
			
		||||
```
 | 
			
		||||
- `documentation` 解析器的文档信息
 | 
			
		||||
- `valueType` 程序本身需要的值类型
 | 
			
		||||
 | 
			
		||||
2. 添加命令
 | 
			
		||||
```c
 | 
			
		||||
@@ -226,6 +227,16 @@ char **argParseGetGlobalArgList(ArgParse *argParse, char *opt, int *len);
 | 
			
		||||
- `opt` 参数选项
 | 
			
		||||
- `len` 参数个数
 | 
			
		||||
 | 
			
		||||
8. 获取程序值
 | 
			
		||||
该值为非命令的值,类似`gcc main.c`,该类程序没有使用命令,因此该值就是`main.c`
 | 
			
		||||
```c
 | 
			
		||||
char  *argParseGetVal(ArgParse *argParse);
 | 
			
		||||
char **argParseGetValList(ArgParse *argParse, int *len);
 | 
			
		||||
```
 | 
			
		||||
- `argParse` 解析器
 | 
			
		||||
- `len` 参数个数
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 触发检测API
 | 
			
		||||
1. 检测当前检测的命令的某个选项是否触发
 | 
			
		||||
```c
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ import os
 | 
			
		||||
 | 
			
		||||
class loggingRecipe(ConanFile):
 | 
			
		||||
    name = "cargparse"
 | 
			
		||||
    version = "0.2.0"
 | 
			
		||||
    version = "0.3.0"
 | 
			
		||||
    license = "MIT"
 | 
			
		||||
    author = "321640253@qq.com"
 | 
			
		||||
    url = "https://gitea.youmetme.wang/youmetme/logging"
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
ArgParse *Init() {
 | 
			
		||||
    ArgParse *ap = argParseInit("简单的命令行工具示例");
 | 
			
		||||
    ArgParse *ap = argParseInit("简单的命令行工具示例",NOVALUE);
 | 
			
		||||
 | 
			
		||||
    // 添加第一个命令
 | 
			
		||||
    Command *cmd = argParseAddCommand(
 | 
			
		||||
 
 | 
			
		||||
@@ -69,19 +69,25 @@ typedef struct ArgParse {
 | 
			
		||||
    struct CommandArgs **global_args;     // 全局参数
 | 
			
		||||
    int                  global_args_len; // 全局参数个数
 | 
			
		||||
    char                *documentation;   // 帮助文档
 | 
			
		||||
    ArgParseValueType value_type; // 值类型 程序默认需要的值例如 gcc main.c
 | 
			
		||||
 | 
			
		||||
    /* 解析所用到的属性*/
 | 
			
		||||
    struct Command *current_command; // 当前解析到的命令
 | 
			
		||||
    int             argc;            // 参数个数
 | 
			
		||||
    char          **argv;            // 参数列表
 | 
			
		||||
    char          **val;
 | 
			
		||||
    int             val_len;
 | 
			
		||||
    int             argc; // 参数个数
 | 
			
		||||
    char          **argv; // 参数列表
 | 
			
		||||
} ArgParse;
 | 
			
		||||
 | 
			
		||||
/** Start---------------构造API---------------- */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief 初始化解析器
 | 
			
		||||
 * @param documentation 帮助文档
 | 
			
		||||
 * @param value_type 值类型,程序默认需要的值例如 gcc main.c
 | 
			
		||||
 * @return ArgParse* 解析器指针
 | 
			
		||||
 */
 | 
			
		||||
ArgParse *argParseInit(char *documentation);
 | 
			
		||||
ArgParse *argParseInit(char *documentation, ArgParseValueType value_type);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief 释放解析器
 | 
			
		||||
@@ -268,6 +274,9 @@ bool argParseCheckCommandTriggered(ArgParse *argParse, char *command_name);
 | 
			
		||||
 */
 | 
			
		||||
bool argParseCheckGlobalTriggered(ArgParse *argParse, char *opt);
 | 
			
		||||
 | 
			
		||||
char  *argParseGetVal(ArgParse *argParse);
 | 
			
		||||
char **argParseGetValList(ArgParse *argParse, int *len);
 | 
			
		||||
 | 
			
		||||
/** End----------------解析API---------------- */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -294,10 +303,10 @@ char *argParseGenerateHelp(ArgParse *argParse);
 | 
			
		||||
char *
 | 
			
		||||
argParseGenerateArgErrorMsg(ArgParse *argParse, char *name, bool short_flag);
 | 
			
		||||
 | 
			
		||||
_Noreturn void argParseError(ArgParse *argParse,
 | 
			
		||||
                             Command  *lastCommand,
 | 
			
		||||
                             char     *prefix,
 | 
			
		||||
                             char     *suffix);
 | 
			
		||||
_Noreturn void argParseError(ArgParse   *argParse,
 | 
			
		||||
                             Command    *lastCommand,
 | 
			
		||||
                             const char *prefix,
 | 
			
		||||
                             const char *suffix);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										174
									
								
								src/ArgParse.c
									
									
									
									
									
								
							
							
						
						
									
										174
									
								
								src/ArgParse.c
									
									
									
									
									
								
							@@ -12,7 +12,7 @@ static bool _COLOR    = true; // 是否启用颜色
 | 
			
		||||
 | 
			
		||||
void argParseDisableAutoHelp() { _AutoHelp = false; }
 | 
			
		||||
 | 
			
		||||
ArgParse *argParseInit(char *documentation) {
 | 
			
		||||
ArgParse *argParseInit(char *documentation, ArgParseValueType value_type) {
 | 
			
		||||
    ArgParse *argParse = malloc(sizeof(ArgParse));
 | 
			
		||||
    if (argParse == NULL) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
@@ -26,6 +26,9 @@ ArgParse *argParseInit(char *documentation) {
 | 
			
		||||
    argParse->argc            = 0;
 | 
			
		||||
    argParse->argv            = NULL;
 | 
			
		||||
    argParse->documentation   = stringNewCopy(documentation);
 | 
			
		||||
    argParse->value_type      = value_type;
 | 
			
		||||
    argParse->val             = NULL;
 | 
			
		||||
    argParse->val_len         = 0;
 | 
			
		||||
 | 
			
		||||
    argParseAutoHelp(argParse);
 | 
			
		||||
 | 
			
		||||
@@ -259,7 +262,16 @@ void __freeCommand(Command *command) {
 | 
			
		||||
    free(command->sub_commands);
 | 
			
		||||
    free(command->name);
 | 
			
		||||
    free(command->help);
 | 
			
		||||
    free(command->args);
 | 
			
		||||
    free(command->default_val);
 | 
			
		||||
 | 
			
		||||
    if (command->val_len > 0) {
 | 
			
		||||
        for (size_t i = 0; i < command->val_len; i++) {
 | 
			
		||||
            free(command->val[i]);
 | 
			
		||||
        }
 | 
			
		||||
        free(command->val);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    free(command);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -274,7 +286,15 @@ void argParseFree(ArgParse *argParse) {
 | 
			
		||||
    for (size_t i = 0; i < argParse->global_args_len; i++) {
 | 
			
		||||
        __freeCommandArgs(argParse->global_args[i]);
 | 
			
		||||
    }
 | 
			
		||||
    if (argParse->val_len > 0) {
 | 
			
		||||
        for (size_t i = 0; i < argParse->val_len; i++) {
 | 
			
		||||
            free(argParse->val[i]);
 | 
			
		||||
        }
 | 
			
		||||
        free(argParse->val);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    free(argParse->global_args);
 | 
			
		||||
    free(argParse->documentation);
 | 
			
		||||
    free(argParse);
 | 
			
		||||
}
 | 
			
		||||
/** End----------------内存释放API---------------- */
 | 
			
		||||
@@ -369,25 +389,79 @@ int __processSubCommand(ArgParse *argParse,
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int __processVal(ArgParse *argParse, int index) {
 | 
			
		||||
    CommandArgs *arg = NULL;
 | 
			
		||||
 | 
			
		||||
    for (int i = index; i < argParse->argc; i++) {
 | 
			
		||||
        ArgType argType = checkArgType(argParse->argv[i]);
 | 
			
		||||
        switch (argType) {
 | 
			
		||||
        case COMMAND:
 | 
			
		||||
            argParseSetVal(argParse, argParse->argv[i]);
 | 
			
		||||
            break;
 | 
			
		||||
        case LONG_ARG:
 | 
			
		||||
            // 处理全局命令长选项
 | 
			
		||||
            arg = argParseFindGlobalArgs(argParse, argParse->argv[i], false);
 | 
			
		||||
            if (arg == NULL) {
 | 
			
		||||
                char *msg = argParseGenerateArgErrorMsg(
 | 
			
		||||
                    argParse, argParse->argv[i], false);
 | 
			
		||||
                argParseError(argParse, argParse->current_command, msg, NULL);
 | 
			
		||||
                return -1;
 | 
			
		||||
            }
 | 
			
		||||
            i = __processArgs(argParse, arg, i);
 | 
			
		||||
            break;
 | 
			
		||||
        case SHORT_ARG:
 | 
			
		||||
            // 处理全局命令短选项
 | 
			
		||||
            arg = argParseFindGlobalArgs(argParse, argParse->argv[i], true);
 | 
			
		||||
            if (arg == NULL) {
 | 
			
		||||
                char *msg = argParseGenerateArgErrorMsg(
 | 
			
		||||
                    argParse, argParse->argv[i], true);
 | 
			
		||||
                argParseError(argParse, argParse->current_command, msg, NULL);
 | 
			
		||||
                return -1; // 错误处理
 | 
			
		||||
            }
 | 
			
		||||
            i = __processArgs(
 | 
			
		||||
                argParse, arg, i); // 解析参数值并返回以解析到的索引位置
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            argParseError(
 | 
			
		||||
                argParse, argParse->current_command, "unknown error", NULL);
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return argParse->argc - 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 处理命令参数
 | 
			
		||||
 | 
			
		||||
int __processCommand(ArgParse *argParse, char *name, int command_index) {
 | 
			
		||||
    Command *command = argParseFindCommand(argParse, name);
 | 
			
		||||
    if (command == NULL) {
 | 
			
		||||
    CommandArgs *arg     = NULL;
 | 
			
		||||
    Command     *command = NULL;
 | 
			
		||||
 | 
			
		||||
        argParseError(argParse, command, "Command not found", NULL);
 | 
			
		||||
    command              = argParseFindCommand(argParse, name); // 查找命令
 | 
			
		||||
 | 
			
		||||
    if (command == NULL && argParse->value_type == NOVALUE) {
 | 
			
		||||
        char *msg = NULL;
 | 
			
		||||
        if (name != NULL) {
 | 
			
		||||
            msg = stringNewCopy("\033[1;31mERROR\033[0m:");
 | 
			
		||||
            __catStr(&msg, 1, name);
 | 
			
		||||
            __catStr(&msg, 1, " is not a valid command");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        argParseError(argParse, command, msg, NULL);
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    command->is_trigged       = true; // 标记命令被触发
 | 
			
		||||
    if (command == NULL && argParse->value_type != NOVALUE) {
 | 
			
		||||
        return __processVal(argParse, command_index);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    CommandArgs *arg          = NULL;
 | 
			
		||||
    argParse->current_command = command;
 | 
			
		||||
    if (command != NULL) {
 | 
			
		||||
        command->is_trigged       = true; // 标记命令被触发
 | 
			
		||||
        argParse->current_command = command;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (int i = command_index + 1; i < argParse->argc; i++) {
 | 
			
		||||
        ArgType argType = checkArgType(argParse->argv[i]);
 | 
			
		||||
        switch (argType) {
 | 
			
		||||
        case COMMAND:
 | 
			
		||||
        case COMMAND: {
 | 
			
		||||
            // 命令无值则处理子命令
 | 
			
		||||
            if (command->value_type == NOVALUE) {
 | 
			
		||||
                __processSubCommand(argParse, command, argParse->argv[i], i);
 | 
			
		||||
@@ -397,6 +471,7 @@ int __processCommand(ArgParse *argParse, char *name, int command_index) {
 | 
			
		||||
                argParseSetCommandVal(command, argParse->argv[i]);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case LONG_ARG:
 | 
			
		||||
            // 处理命令长选项
 | 
			
		||||
            arg = argParseFindCommandArgs(command, argParse->argv[i], false);
 | 
			
		||||
@@ -462,6 +537,7 @@ void argParseParse(ArgParse *argParse, int argc, char *argv[]) {
 | 
			
		||||
        ArgType argType = checkArgType(argv[i]);
 | 
			
		||||
        switch (argType) {
 | 
			
		||||
        case COMMAND:
 | 
			
		||||
            // 处理命令
 | 
			
		||||
            i = __processCommand(argParse, argv[i], i);
 | 
			
		||||
            break;
 | 
			
		||||
        case LONG_ARG: // 处理全局长选项
 | 
			
		||||
@@ -638,44 +714,27 @@ char **argParseGetGlobalArgList(ArgParse *argParse, char *opt, int *len) {
 | 
			
		||||
    return arg->val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t __getStrlen(char *str) {
 | 
			
		||||
    if (str == NULL) {
 | 
			
		||||
        return 0;
 | 
			
		||||
char **argParseGetValList(ArgParse *argParse, int *len) {
 | 
			
		||||
    if (argParse == NULL) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    return strlen(str);
 | 
			
		||||
 | 
			
		||||
    if (argParse->val_len == 0) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    *len = argParse->val_len;
 | 
			
		||||
    return argParse->val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __catStr(char **dst, int count, ...) {
 | 
			
		||||
    va_list args;
 | 
			
		||||
    va_start(args, count);
 | 
			
		||||
 | 
			
		||||
    size_t total_len = 0;
 | 
			
		||||
    total_len        = __getStrlen(*dst);
 | 
			
		||||
 | 
			
		||||
    // 计算总长度
 | 
			
		||||
    char *temp       = NULL;
 | 
			
		||||
    for (int i = 0; i < count; i++) {
 | 
			
		||||
        temp = va_arg(args, char *);
 | 
			
		||||
        total_len += __getStrlen(temp);
 | 
			
		||||
    }
 | 
			
		||||
    va_end(args);
 | 
			
		||||
 | 
			
		||||
    // 分配内存
 | 
			
		||||
    *dst = realloc(*dst, total_len + 1); // +1 是为了存储字符串结束符 '\0'
 | 
			
		||||
    if (*dst == NULL) {
 | 
			
		||||
        va_end(args);
 | 
			
		||||
        return; // 处理内存分配失败
 | 
			
		||||
char *argParseGetVal(ArgParse *argParse) {
 | 
			
		||||
    if (argParse == NULL) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 拼接字符串
 | 
			
		||||
    va_start(args, count);
 | 
			
		||||
    temp = NULL;
 | 
			
		||||
    for (int i = 0; i < count; i++) {
 | 
			
		||||
        temp = va_arg(args, char *);
 | 
			
		||||
        strcat(*dst, temp);
 | 
			
		||||
    if (argParse->val_len == 0) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    va_end(args);
 | 
			
		||||
    return argParse->val[0];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *argParseGenerateHelpForCommand(Command *command) {
 | 
			
		||||
@@ -759,25 +818,41 @@ bool argParseCheckCommandTriggered(ArgParse *argParse, char *command_name) {
 | 
			
		||||
    return command->is_trigged;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_Noreturn void argParseError(ArgParse *argParse,
 | 
			
		||||
                             Command  *lastCommand,
 | 
			
		||||
                             char     *prefix,
 | 
			
		||||
                             char     *suffix) {
 | 
			
		||||
_Noreturn void argParseError(ArgParse   *argParse,
 | 
			
		||||
                             Command    *lastCommand,
 | 
			
		||||
                             const char *prefix,
 | 
			
		||||
                             const char *suffix) {
 | 
			
		||||
    if (argParse == NULL) {
 | 
			
		||||
        printf("ERROR: Parse is NULL\n");
 | 
			
		||||
        exit(1);
 | 
			
		||||
    }
 | 
			
		||||
    if (lastCommand == NULL) {
 | 
			
		||||
        char *mgs = stringNewCopy("");
 | 
			
		||||
        if (prefix != NULL) {
 | 
			
		||||
            __catStr(&mgs, 1, prefix);
 | 
			
		||||
        }
 | 
			
		||||
        char *help = argParseGenerateHelp(argParse);
 | 
			
		||||
        printf("\033[1;31mERROR\033[0m: Last command is unknown\n");
 | 
			
		||||
        printf("%s\n", help);
 | 
			
		||||
 | 
			
		||||
        if (help != NULL) {
 | 
			
		||||
            __catStr(&mgs, 2, "\n", help);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (suffix != NULL) {
 | 
			
		||||
            __catStr(&mgs, 2, "\n", suffix);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // printf("\033[1;31mERROR\033[0m: Last command is unknown\n");
 | 
			
		||||
        printf("%s\n", mgs);
 | 
			
		||||
        free(mgs);
 | 
			
		||||
        free(help);
 | 
			
		||||
        argParseFree(argParse);
 | 
			
		||||
        exit(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    char *ErrorMsg = NULL;
 | 
			
		||||
 | 
			
		||||
    if (prefix != NULL) {
 | 
			
		||||
        ErrorMsg = stringNewCopy(prefix);
 | 
			
		||||
        ErrorMsg = stringNewCopy((char *)prefix);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    char *command_help_msg     = argParseGenerateHelpForCommand(lastCommand);
 | 
			
		||||
@@ -794,8 +869,7 @@ _Noreturn void argParseError(ArgParse *argParse,
 | 
			
		||||
    printf("%s\n", ErrorMsg);
 | 
			
		||||
    free(ErrorMsg);
 | 
			
		||||
    free(command_help_msg);
 | 
			
		||||
    free(prefix);
 | 
			
		||||
    free(suffix);
 | 
			
		||||
    argParseFree(argParse);
 | 
			
		||||
    exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,7 @@
 | 
			
		||||
#include "ArgParseTools.h"
 | 
			
		||||
#include "ArgParse.h"
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
@@ -242,4 +244,85 @@ bool argParseSetCommandVal(Command *command, char *val) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief 设置解析值,该值为程序所需的无命令值例如`gcc mian.c`的`main.c`
 | 
			
		||||
 * @param argParse 解析器
 | 
			
		||||
 * @param val 值
 | 
			
		||||
 * @return 成功返回true,失败返回false
 | 
			
		||||
 */
 | 
			
		||||
bool argParseSetVal(ArgParse *argParse, char *val) {
 | 
			
		||||
 | 
			
		||||
    if (argParse->value_type == MULTIVALUE) { // 多值
 | 
			
		||||
        argParse->val =
 | 
			
		||||
            realloc(argParse->val, (argParse->val_len + 1) * sizeof(char *));
 | 
			
		||||
        if (argParse->val == NULL) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        argParse->val[argParse->val_len] = stringNewCopy(val);
 | 
			
		||||
        if (argParse->val[argParse->val_len] == NULL) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        argParse->val_len++;
 | 
			
		||||
        return true;
 | 
			
		||||
    } else if (argParse->value_type == SINGLEVALUE) { // 单值
 | 
			
		||||
        if (argParse->val != NULL) {
 | 
			
		||||
            free(argParse->val);
 | 
			
		||||
        }
 | 
			
		||||
        argParse->val = malloc(sizeof(char *));
 | 
			
		||||
 | 
			
		||||
        if (argParse->val == NULL) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        argParse->val[0] = stringNewCopy(val); // 分配内存
 | 
			
		||||
        if (argParse->val[0] == NULL) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        argParse->val_len = 1;
 | 
			
		||||
        return true;
 | 
			
		||||
    } else if (argParse->value_type == NOVALUE) { // 无值
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t __getStrlen(char *str) {
 | 
			
		||||
    if (str == NULL) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    return strlen(str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __catStr(char **dst, int count, ...) {
 | 
			
		||||
    va_list args;
 | 
			
		||||
    va_start(args, count);
 | 
			
		||||
 | 
			
		||||
    size_t total_len = 0;
 | 
			
		||||
    total_len        = __getStrlen(*dst);
 | 
			
		||||
 | 
			
		||||
    // 计算总长度
 | 
			
		||||
    char *temp       = NULL;
 | 
			
		||||
    for (int i = 0; i < count; i++) {
 | 
			
		||||
        temp = va_arg(args, char *);
 | 
			
		||||
        total_len += __getStrlen(temp);
 | 
			
		||||
    }
 | 
			
		||||
    va_end(args);
 | 
			
		||||
 | 
			
		||||
    // 分配内存
 | 
			
		||||
    *dst = realloc(*dst, total_len + 1); // +1 是为了存储字符串结束符 '\0'
 | 
			
		||||
    if (*dst == NULL) {
 | 
			
		||||
        va_end(args);
 | 
			
		||||
        return; // 处理内存分配失败
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 拼接字符串
 | 
			
		||||
    va_start(args, count);
 | 
			
		||||
    temp = NULL;
 | 
			
		||||
    for (int i = 0; i < count; i++) {
 | 
			
		||||
        temp = va_arg(args, char *);
 | 
			
		||||
        strcat(*dst, temp);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    va_end(args);
 | 
			
		||||
}
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
 | 
			
		||||
#include "ArgParse.h"
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
@@ -45,6 +46,8 @@ bool argParseSetArgVal(CommandArgs *args, char *val); // 设置命令参数值
 | 
			
		||||
 | 
			
		||||
bool argParseSetCommandVal(Command *command, char *val); // 设置命令值
 | 
			
		||||
 | 
			
		||||
bool argParseSetVal(ArgParse *argParse, char *val); // 设置值
 | 
			
		||||
 | 
			
		||||
ArgType checkArgType(char *arg); // 检查参数类型
 | 
			
		||||
 | 
			
		||||
Command *argParseFindCommand(ArgParse *argParse, char *name); // 查找命令
 | 
			
		||||
@@ -59,7 +62,9 @@ CommandArgs *argParseFindGlobalArgs(ArgParse *argParse,
 | 
			
		||||
                                    char     *name,
 | 
			
		||||
                                    bool      short_flag); // 查找全局参数
 | 
			
		||||
 | 
			
		||||
char *stringNewCopy(char *str); // 创建字符串副本
 | 
			
		||||
char  *stringNewCopy(char *str);             // 创建字符串副本
 | 
			
		||||
void   __catStr(char **dst, int count, ...); // 字符串拼接
 | 
			
		||||
size_t __getStrlen(char *str);               // 获取字符串长度
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -32,3 +32,8 @@ add_executable(${PROJECT_NAME}unknow_command_arg test_unknow_command.c)
 | 
			
		||||
target_link_libraries(${PROJECT_NAME}unknow_command_arg CArgParse)
 | 
			
		||||
add_test(${PROJECT_NAME}unknow_command_arg ${PROJECT_NAME}unknow_command_arg install --unknow)
 | 
			
		||||
set_tests_properties(${PROJECT_NAME}unknow_command_arg PROPERTIES WILL_FAIL TRUE)
 | 
			
		||||
 | 
			
		||||
# 未知命令选项测试,预期打印该命令的帮助信息
 | 
			
		||||
add_executable(${PROJECT_NAME}val test_val.c)
 | 
			
		||||
target_link_libraries(${PROJECT_NAME}val CArgParse)
 | 
			
		||||
add_test(${PROJECT_NAME}val ${PROJECT_NAME}val file1.txt file2.txt file3.txt -v -q)
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
ArgParse *initArgParse() {
 | 
			
		||||
    ArgParse *argparse    = argParseInit("测试程序");
 | 
			
		||||
    ArgParse *argparse    = argParseInit("测试程序",NOVALUE);
 | 
			
		||||
    Command  *command     = NULL;
 | 
			
		||||
    Command  *sub_command = NULL;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										122
									
								
								tests/test_val.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								tests/test_val.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,122 @@
 | 
			
		||||
#include "ArgParse.h"
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
ArgParse *initArgParse() {
 | 
			
		||||
    ArgParse *argparse    = argParseInit("测试程序", MULTIVALUE);
 | 
			
		||||
    Command  *command     = NULL;
 | 
			
		||||
    Command  *sub_command = NULL;
 | 
			
		||||
 | 
			
		||||
    // add global arguments
 | 
			
		||||
    argParseAddGlobalArg(argparse,
 | 
			
		||||
                         "-v",
 | 
			
		||||
                         "--version",
 | 
			
		||||
                         "Show version",
 | 
			
		||||
                         NULL,
 | 
			
		||||
                         NULL,
 | 
			
		||||
                         false,
 | 
			
		||||
                         NOVALUE);
 | 
			
		||||
    argParseAddGlobalArg(
 | 
			
		||||
        argparse, "-q", "--quiet", "Quiet mode", NULL, NULL, false, NOVALUE);
 | 
			
		||||
 | 
			
		||||
    // add arguments
 | 
			
		||||
    command = argParseAddCommand(
 | 
			
		||||
        argparse, "install", "Install the package", NULL, NULL, NULL, NOVALUE);
 | 
			
		||||
    argParseAddArg(command,
 | 
			
		||||
                   "-i",
 | 
			
		||||
                   "--index",
 | 
			
		||||
                   "Index URL",
 | 
			
		||||
                   "https://example.com",
 | 
			
		||||
                   NULL,
 | 
			
		||||
                   false,
 | 
			
		||||
                   SINGLEVALUE);
 | 
			
		||||
    argParseAddArg(command,
 | 
			
		||||
                   "-f",
 | 
			
		||||
                   "--file",
 | 
			
		||||
                   "Package file",
 | 
			
		||||
                   "package.json",
 | 
			
		||||
                   NULL,
 | 
			
		||||
                   false,
 | 
			
		||||
                   MULTIVALUE);
 | 
			
		||||
    argParseAddArg(command,
 | 
			
		||||
                   "-p",
 | 
			
		||||
                   "--package",
 | 
			
		||||
                   "Package file",
 | 
			
		||||
                   "package.json",
 | 
			
		||||
                   NULL,
 | 
			
		||||
                   false,
 | 
			
		||||
                   MULTIVALUE);
 | 
			
		||||
 | 
			
		||||
    sub_command = argParseAddSubCommand(
 | 
			
		||||
        command, "tools", "Install tools", NULL, NULL, NULL, MULTIVALUE);
 | 
			
		||||
 | 
			
		||||
    argParseAddArg(sub_command,
 | 
			
		||||
                   "-t",
 | 
			
		||||
                   "--tool",
 | 
			
		||||
                   "Tool name",
 | 
			
		||||
                   "Tool name",
 | 
			
		||||
                   NULL,
 | 
			
		||||
                   true,
 | 
			
		||||
                   MULTIVALUE);
 | 
			
		||||
    sub_command = argParseAddSubCommand(
 | 
			
		||||
        command, "tools_sub", "Install tools", NULL, NULL, NULL, MULTIVALUE);
 | 
			
		||||
 | 
			
		||||
    argParseAddArg(sub_command,
 | 
			
		||||
                   "-s",
 | 
			
		||||
                   "--source",
 | 
			
		||||
                   "test_source",
 | 
			
		||||
                   "tools subcommand test",
 | 
			
		||||
                   NULL,
 | 
			
		||||
                   true,
 | 
			
		||||
                   MULTIVALUE);
 | 
			
		||||
 | 
			
		||||
    command = argParseAddCommand(argparse,
 | 
			
		||||
                                 "uninstall",
 | 
			
		||||
                                 "Uninstall the package",
 | 
			
		||||
                                 NULL,
 | 
			
		||||
                                 NULL,
 | 
			
		||||
                                 NULL,
 | 
			
		||||
                                 SINGLEVALUE);
 | 
			
		||||
    argParseAddArg(command,
 | 
			
		||||
                   "-p",
 | 
			
		||||
                   "--package",
 | 
			
		||||
                   "Package name",
 | 
			
		||||
                   "Package name",
 | 
			
		||||
                   NULL,
 | 
			
		||||
                   true,
 | 
			
		||||
                   MULTIVALUE);
 | 
			
		||||
 | 
			
		||||
    return argparse;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[]) {
 | 
			
		||||
    ArgParse *argparse = initArgParse();
 | 
			
		||||
 | 
			
		||||
    argParseParse(argparse, argc, argv);
 | 
			
		||||
 | 
			
		||||
    char *val = argParseGetVal(argparse);
 | 
			
		||||
    if (val) {
 | 
			
		||||
        printf("val: %s\n", val);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int    len  = 0;
 | 
			
		||||
    char **vals = argParseGetValList(argparse, &len);
 | 
			
		||||
 | 
			
		||||
    char *test_val[3] = {"file1.txt", "file2.txt", "file3.txt"};
 | 
			
		||||
 | 
			
		||||
    if (vals) {
 | 
			
		||||
        for (int i = 0; i < len; i++) {
 | 
			
		||||
            printf("vals: %s\n", vals[i]);
 | 
			
		||||
            assert(strcmp(vals[i], test_val[i]) == 0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    assert(argParseCheckGlobalTriggered(argparse, "-v"));
 | 
			
		||||
    assert(argParseCheckGlobalTriggered(argparse, "-q"));
 | 
			
		||||
 | 
			
		||||
    argParseFree(argparse);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user