Files
scc/libs/argparse/include/argparse.h
zzy 4144f7841c refactor(argparse): 将null替换为nullptr以提高C++兼容性
- 在argparse库中将所有null指针常量替换为nullptr
- 更新头文件和源文件中的指针初始化和比较操作
- 修改测试文件中的相关断言检查
- 更新AST定义文件中的注释说明
2026-04-05 20:18:09 +08:00

241 lines
8.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#ifndef __SCC_ARGPARSE_H__
#define __SCC_ARGPARSE_H__
#include "optparse.h"
#include <scc_core.h>
// TODO: 实现更多高级功能
// 1. 支持子命令嵌套层级限制
// 2. 支持选项分组显示Grouping
// 3. 支持自动补全脚本生成Bash/Zsh/Fish
// 4. 支持配置文件解析
// 5. 支持国际化i18n
typedef struct scc_argparse_spec scc_argparse_spec_t;
typedef struct scc_argparse_arg scc_argparse_arg_t;
typedef struct scc_argparse_opt scc_argparse_opt_t;
typedef struct scc_argparse_cmd scc_argparse_cmd_t;
typedef SCC_VEC(scc_argparse_arg_t) scc_argparse_arg_vec_t;
typedef SCC_VEC(scc_argparse_opt_t) scc_argparse_opt_vec_t;
typedef SCC_VEC(scc_argparse_cmd_t) scc_argparse_cmd_vec_t;
typedef enum scc_argparse_val_type {
SCC_ARGPARSE_VAL_TYPE_UNKNOWN,
SCC_ARGPARSE_VAL_TYPE_STRING,
SCC_ARGPARSE_VAL_TYPE_BOOL,
SCC_ARGPARSE_VAL_TYPE_INT,
SCC_ARGPARSE_VAL_TYPE_FLOAT,
SCC_ARGPARSE_VAL_TYPE_ENUM,
SCC_ARGPARSE_VAL_TYPE_LIST,
SCC_ARGPARSE_VAL_TYPE_COUNT,
} scc_argparse_val_type_t;
typedef enum scc_argparse_err {
SCC_ARGPARSE_ERR_NONE,
SCC_ARGPARSE_ERR_PNT_DEFAULT,
SCC_ARGPARSE_ERR_UNKNOWN_ERR,
SCC_ARGPARSE_ERR_INVALID_ARG,
SCC_ARGPARSE_ERR_INVALID_VALUE,
SCC_ARGPARSE_ERR_MISSING_ARG,
SCC_ARGPARSE_ERR_MISSING_VALUE,
SCC_ARGPARSE_ERR_UNKNOWN_ARG,
SCC_ARGPARSE_ERR_UNKNOWN_VALUE,
} scc_argparse_err_t;
typedef SCC_VEC(const char *) scc_argparse_list_t;
// 约束规范结构体
struct scc_argparse_spec {
scc_argparse_val_type_t value_type; // 值类型
const char *raw_value;
// 存储位置
union {
cbool *bool_store; // 布尔值存储
int *int_store; // 整数存储
float *float_store; // 浮点数存储
const char **str_store; // 字符串存储
char **str_alloc_store; // 字符串存储使用alloc需要free
void **ptr_store; // 通用指针存储
scc_argparse_list_t *vec_store; // 新增:指向字符串向量的指针
} store;
// 枚举值约束
struct {
const char **values; // 枚举值数组
int count; // 枚举值数量
} choices;
// 其他约束标志
cbool flag_required; // 是否必须
cbool flag_store_as_count; // 是否存储为计数(如 -vvv 返回3
cbool flag_allow_empty; // 是否允许空字符串
cbool flag_hidden; // 是否隐藏(不显示在帮助)
cbool flag_takes_multiple; // 是否接受多个值(如 -I dir1 -I dir2
cbool flag_parse_complex; // 是否进行复杂解析(如 1K, 2M, 3G
};
struct scc_argparse_arg {
scc_argparse_spec_t spec;
const char *name;
const char *description;
};
struct scc_argparse_opt {
scc_argparse_spec_t spec;
char short_name;
const char *long_name;
const char *description;
};
struct scc_argparse_cmd {
const char *name;
const char *description;
scc_argparse_arg_vec_t args;
scc_argparse_opt_vec_t opts;
scc_argparse_cmd_vec_t subcmds;
};
typedef enum {
SCC_ARGPARSE_LANG_EN,
SCC_ARGPARSE_LANG_ZH,
} scc_argparse_lang_t;
typedef struct {
const char *prog_name;
const char *version;
const char *description;
const char *epilog;
scc_argparse_cmd_t root_cmd;
scc_argparse_lang_t lang;
cbool need_help;
cbool need_version;
cbool need_debug;
} scc_argparse_t;
typedef SCC_VEC(scc_optparse_opt_t) scc_optparse_opt_vec_t;
typedef struct {
scc_argparse_cmd_t *current_cmd; // 当前正在解析的命令
scc_optparse_t optparse; // 底层解析器
scc_optparse_opt_vec_t opts; // 当前命令的选项列表
scc_optparse_result_t result;
int positional_index; // 当前处理的位置参数索引
cbool parsing_done; // 是否已完成解析
scc_argparse_lang_t lang;
} scc_argparse_context_t;
void scc_argparse_init(scc_argparse_t *parser, const char *program_name,
const char *description);
scc_argparse_cmd_t *scc_argparse_get_root(scc_argparse_t *parser);
void scc_argparse_drop(scc_argparse_t *parser);
int scc_argparse_parse(scc_argparse_t *parser, int argc, const char **argv);
void scc_argparse_cmd_init(scc_argparse_cmd_t *cmd, const char *name,
const char *description);
void scc_argparse_cmd_drop(scc_argparse_cmd_t *cmd);
void scc_argparse_cmd_add_arg(scc_argparse_cmd_t *cmd,
const scc_argparse_arg_t *arg);
void scc_argparse_cmd_add_opt(scc_argparse_cmd_t *cmd,
const scc_argparse_opt_t *opt);
void scc_argparse_cmd_add_subcmd(scc_argparse_cmd_t *cmd,
const scc_argparse_cmd_t *subcmd);
void scc_argparse_print_help(scc_argparse_t *parser, scc_argparse_cmd_t *cmd);
void scc_argparse_print_error(scc_argparse_context_t *ctx,
scc_argparse_err_t err);
static inline void scc_argparse_spec_init(scc_argparse_spec_t *spec) {
spec->value_type = SCC_ARGPARSE_VAL_TYPE_STRING;
spec->raw_value = nullptr;
spec->store.ptr_store = nullptr;
spec->choices.count = 0;
spec->choices.values = nullptr;
spec->flag_required = false;
spec->flag_store_as_count = false;
spec->flag_allow_empty = false;
spec->flag_hidden = false;
spec->flag_takes_multiple = false;
spec->flag_parse_complex = false;
}
static inline void scc_argparse_opt_init(scc_argparse_opt_t *opt,
char short_name, const char *long_name,
const char *desc) {
opt->short_name = short_name;
opt->long_name = long_name;
opt->description = desc;
scc_argparse_spec_init(&opt->spec);
}
static inline void scc_argparse_arg_init(scc_argparse_arg_t *arg,
const char *name, const char *desc) {
arg->name = name;
arg->description = desc;
scc_argparse_spec_init(&arg->spec);
}
static inline void scc_argparse_spec_setup_bool(scc_argparse_spec_t *spec,
cbool *store) {
spec->value_type = SCC_ARGPARSE_VAL_TYPE_BOOL;
spec->store.bool_store = store;
}
static inline void scc_argparse_spec_setup_count(scc_argparse_spec_t *spec,
int *store) {
spec->value_type = SCC_ARGPARSE_VAL_TYPE_COUNT;
spec->flag_store_as_count = true; // 自动设为计数模式
spec->store.int_store = store;
}
static inline void scc_argparse_spec_setup_string(scc_argparse_spec_t *spec,
const char **store) {
spec->value_type = SCC_ARGPARSE_VAL_TYPE_STRING;
spec->store.str_store = store;
}
static inline void scc_argparse_spec_setup_int(scc_argparse_spec_t *spec,
int *store) {
spec->value_type = SCC_ARGPARSE_VAL_TYPE_INT;
spec->store.int_store = store;
}
static inline void scc_argparse_spec_setup_float(scc_argparse_spec_t *spec,
float *store) {
spec->value_type = SCC_ARGPARSE_VAL_TYPE_FLOAT;
spec->store.float_store = store;
}
static inline void scc_argparse_spec_setup_choices(scc_argparse_spec_t *spec,
const char **values,
int count) {
spec->value_type = SCC_ARGPARSE_VAL_TYPE_ENUM;
spec->choices.values = values;
spec->choices.count = count;
}
// 添加设置列表的辅助函数(内联)
static inline void scc_argparse_spec_setup_list(scc_argparse_spec_t *spec,
scc_argparse_list_t *vec) {
spec->value_type = SCC_ARGPARSE_VAL_TYPE_LIST;
spec->store.vec_store = vec;
// 自动设置 flag_takes_multiple 为 true因为列表需要多个值
spec->flag_takes_multiple = true;
}
#define SCC_ARGPARSE_MACRO_SETTER(attr) \
static inline void scc_argparse_spec_set_##attr(scc_argparse_spec_t *spec, \
cbool flag) { \
spec->flag_##attr = flag; \
}
SCC_ARGPARSE_MACRO_SETTER(required)
SCC_ARGPARSE_MACRO_SETTER(allow_empty)
SCC_ARGPARSE_MACRO_SETTER(hidden)
SCC_ARGPARSE_MACRO_SETTER(takes_multiple)
SCC_ARGPARSE_MACRO_SETTER(parse_complex)
#endif /* __SCC_ARGPARSE_H__ */