/**
 * @file sh_vset.h.c
 * @author LokLiang
 * @brief sh_vset.h 模块源码
 * @version 0.1
 * @date 2023-09-22
 *
 * @copyright Copyright (c) 2023
 *
 */

#include "sh_vset.h"
#include <string.h>

#undef CONFIG_SYS_LOG_LEVEL
#define CONFIG_SYS_LOG_LEVEL SYS_LOG_LEVEL_INF
#define SYS_LOG_DOMAIN "VSET"
#define CONS_ABORT()
#include "sys_log.h"

#define __ARR_SIZE(ARR) (sizeof(ARR) / sizeof((ARR)[0]))

#define _TYPE_FLAG_UNSIGNED (1 << 0)
#define _TYPE_FLAG_INTEGER (1 << 1)
#define _TYPE_FLAG_FLOAT (1 << 2)
#define _TYPE_FLAG_STRING (1 << 3)

#define _PARAM_CB()               \
    do                            \
    {                             \
        if (cb)                   \
            cb(s_sh_hdl, &value); \
    } while (0)

static sh_t *s_sh_hdl;
static vset_global_cb s_global_cb;

static bool _is_in_option(const char *input, const sh_vset_param_t *p, unsigned size);
static const sh_vset_param_t *_find_option(const char *input, const sh_vset_param_t *p, unsigned size);
static bool _do_completing_option(sh_t *sh_hdl, int argc, const char *argv[], const sh_vset_param_t *p, unsigned size);
static bool _do_completing_enum(const char *option, const sh_vset_param_t *p, unsigned size);

static int _set_dest_unsigned(void *dest, __type_attr_t attr, vset_cb cb, unsigned int value, unsigned int low, unsigned int high);
static int _set_dest_integer(void *dest, __type_attr_t attr, vset_cb cb, signed int value, signed int low, signed int high);
static int _set_dest_float(void *dest, __type_attr_t attr, vset_cb cb, float value, float low, float high);
static int _set_dest_string(void *dest, __type_attr_t attr, vset_cb cb, const char *str, unsigned bufsize);
static int _set_dest_enum(void *dest, __type_attr_t attr, vset_cb cb, const char *value, int type_flag);

static unsigned int _get_unsigned(void *dest, __type_attr_t attr);
static signed int _get_integer(void *dest, __type_attr_t attr);
static float _get_float(void *dest, __type_attr_t attr);
static char *_get_string(void *dest, __type_attr_t attr);
static int _enum_format(char *enum_buf, int buf_len, const char *enum_str);
static int _get_enum_by_key(const char *key, char **match_value, char *enum_buf);
static int _get_enum_by_param(void *dest, __type_attr_t attr, char **match_key, char **match_value, char *enum_buf, bool print_list, bool print_cp);

/**
 * @brief s_attr_to_type_tbl
 * 由变量的具体类型转换到可用于参数解析的范围
 */
static int const s_attr_to_type_tbl[] = {
    [__TYPE_ATTR_CHR] = _PARSE_TYPE_INTEGER,
    [__TYPE_ATTR_BOOL] = _PARSE_TYPE_INTEGER,
    [__TYPE_ATTR_U8] = _PARSE_TYPE_UNSIGNED,
    [__TYPE_ATTR_S8] = _PARSE_TYPE_INTEGER,
    [__TYPE_ATTR_U16] = _PARSE_TYPE_UNSIGNED,
    [__TYPE_ATTR_S16] = _PARSE_TYPE_INTEGER,
    [__TYPE_ATTR_U32] = _PARSE_TYPE_UNSIGNED,
    [__TYPE_ATTR_S32] = _PARSE_TYPE_INTEGER,
    [__TYPE_ATTR_U64] = _PARSE_TYPE_UNSIGNED,
    [__TYPE_ATTR_S64] = _PARSE_TYPE_INTEGER,
    [__TYPE_ATTR_FLOAT] = _PARSE_TYPE_FLOAT,
    [__TYPE_ATTR_DOUBLE] = _PARSE_TYPE_FLOAT,
    [__TYPE_ATTR_STR] = _PARSE_TYPE_STRING,
};

/**
 * @brief 初始化设置
 *
 * @param sh_hdl    设置 shell 的句柄
 * @param global_cb 当任意一个值被修改时回调此函数，可设为 NULL
 */
void vset_init(sh_t *sh_hdl, vset_global_cb global_cb)
{
    s_sh_hdl = sh_hdl;
    s_global_cb = global_cb;
}

/**
 * @brief 直接执行一次 vset_init() 所定义的回调函数
 *
 */
void vset_force_cb(void)
{
    vset_global_cb global_cb = s_global_cb;
    if (global_cb)
    {
        global_cb(s_sh_hdl);
    }
}

/**
 * @brief 一次性根据选项结构 p 解析 argv, 自动选择对应的设置函数进行对变量的设置。
 * 这将导致输入的参数 argc 和 argv 被更新。
 *
 * @details
 * 这将一将性解析全部符合 p 内部符合的参数，并执行对应的处理函数，成功设置的 argc 和 argv 会被删除。
 * 注意如果有任何处理失败的函数不会立即返回，已成功设置的值也不会被恢复，直到全部 argv 被解析过一次后返回。
 *
 * @param sh_hdl    原参数
 * @param argc[i/o] 指向原参数，可能被更新
 * @param argv[i/o] 原参数指针值，可能被更新
 * @param p         选项描述结构体
 * @param size      选项描述结构体的长度
 * @retval 0 所有存在于 sh_vset_param_t::option 的选项被正确设置
 * @retval != 0 首个设置错误的 sh_vset_param_t::option
 */
int vset_option_set(sh_t *sh_hdl, int *argc, const char *argv[], const sh_vset_param_t *p, unsigned size)
{
    int argc_old = *argc;
    const char *err_option = NULL;

    /* 遍历输入参数 argv 在 p 中找到匹配的 p[i].option 对应的 p[i].set_func 并执行 */
    for (int i = 0; i < argc_old; i++)
    {
        for (int j = 0; j < size / sizeof(*p); j++)
        {
            const sh_vset_param_t *pset = &p[j];
            if (strcmp(argv[i], pset->option) == 0) // 匹配到选项
            {
                if (pset->set_func) // 该选有对应的设置函数
                {
                    bool flag = false;
                    argv[i] = NULL;

                    const char *str[] = {
                        "",
                        "",
                    };
                    if (i + 1 < argc_old)
                    {
                        ++i;
                        str[0] = argv[i];
                        argv[i] = NULL;

                        if (strcmp("?", str[0]) == 0)
                        {
                            flag = true;
                            sh_echo(s_sh_hdl, "选项:     %s\r\n", pset->option);
                            if (pset->help)
                            {
                                sh_echo(s_sh_hdl, "说明:     %s\r\n", pset->help);
                            }
                        }
                    }

                    int ret = pset->set_func(str);
                    if (flag)
                    {
                        sh_echo(s_sh_hdl, "========\r\n");
                    }
                    if (ret != 0)
                    {
                        if (err_option == NULL)
                        {
                            err_option = pset->option;
                        }
                        sh_echo(s_sh_hdl, "( 选项 %s )\r\n", pset->option);
                        sh_echo(s_sh_hdl, "========\r\n");
                    }
                }

                break;
            }
        }
    }

    /* 更新已被处理的输入参数 argc 和 argv */
    int argc_new = 0;
    for (int i = 0; i < argc_old; i++)
    {
        if (argv[i] && *argv[i] != '\0')
        {
            argv[argc_new++] = argv[i]; // 更新 argv
        }
    }
    *argc = argc_new; // 更新 argc
    while (argc_new < argc_old)
    {
        argv[argc_new++] = NULL;
    }

    return (int)err_option;
}

/**
 * @brief 为 cp_fn 执行与 set_func 对应的参数补全动作
 *
 * @param sh_hdl    原参数
 * @param argc      原参数
 * @param argv      原参数指针值，可能被更新
 * @param flag      原参数
 * @param p         选项描述结构体
 * @param size      选项描述结构体的长度
 * @retval true 有补全动作， cp_fn 函数不需要进行任何动作
 * @retval false 未补全动作， cp_fn 函数可自行执行补全
 */
bool vset_option_cp(sh_t *sh_hdl, int argc, const char *argv[], bool flag, const sh_vset_param_t *p, unsigned size)
{
    if (flag == false) // 一个参数正在输入
    {
        if (argc > 0 && _is_in_option(argv[argc - 1], p, size)) // 前正在输入的参数有对应存在的候选选项
        {
            _do_completing_option(sh_hdl, argc, argv, p, size); // 执行对选项的补全
            return true;
        }
        else if (argc > 1)
        {
            return _do_completing_enum(argv[argc - 2], p, size); // 执行对 SET_ENUM 中的 ENUM_STR 的补全
        }
        else
        {
            return false;
        }
    }
    else // 当前参数未有任何输入
    {
        const sh_vset_param_t *pset;
        if (argc > 0 && (pset = _find_option(argv[argc - 1], p, size)) != NULL) // 找到上一个输入的参数的对应选项
        {
            vset_cp_enum(1, false, pset->enum_str);
            return true;
        }
        else
        {
            _do_completing_option(sh_hdl, argc, argv, p, size); // 执行对选项的补全
            return true;
        }
    }
}

/**
 * @brief 对应 SET_VAR 所设置的变量的可用自动补全函数，默认补全一个 '?' 号
 *
 * @param sh_hdl    原参数
 * @param argc      原参数
 * @param argv      原参数指针值，可能被更新
 * @param flag      原参数
 */
void vset_cp_hint(sh_t *sh_hdl, int argc, const char *argv[], bool flag)
{
    if (argc + flag == 1)
    {
        sh_completion_resource(sh_hdl, NULL, "? ", NULL);
    }
}

int vset_unsigned(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], unsigned int low, unsigned int high)
{
    SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
    SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
    SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_UNSIGNED, "待设置的参数类型不是正整数");

    if (s_sh_hdl == NULL)
    {
        return -1;
    }
    if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
    {
        sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
        return -1;
    }
    if (s_attr_to_type_tbl[attr] != _PARSE_TYPE_UNSIGNED)
    {
        sh_echo(s_sh_hdl, "待设置的参数类型不是正整数\r\n");
        return -1;
    }

    if (argv[0] == NULL || *argv[0] == '\0')
    {
        sh_echo(s_sh_hdl, "缺少参数\r\n");
        return -1;
    }

    if (strcmp(argv[0], "?") == 0)
    {
        if (high < low)
        {
            low ^= high;
            high ^= low;
            low ^= high;
        }
        sh_echo(s_sh_hdl, "有效范围: %d .. %d\r\n", low, high);
        sh_echo(s_sh_hdl, "当前值:   %u\r\n", _get_unsigned(dest, attr));
        return 0;
    }

    sh_parse_t pv = sh_parse_value(argv[0]);
    switch (pv.type)
    {
    case _PARSE_TYPE_UNSIGNED: // 解析出的参数格式是无符号整型
        return _set_dest_unsigned(dest, attr, cb, pv.value.val_unsigned, low, high);

    default:
        sh_echo(s_sh_hdl, "参数 '%s' 格式错误, 请输入正整数\r\n", argv[0]);
        return -1;
    }
}

int vset_integer(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], signed int low, signed int high)
{
    SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
    SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
    SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_INTEGER, "待设置的参数类型不是带符号整数");

    if (s_sh_hdl == NULL)
    {
        return -1;
    }
    if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
    {
        sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
        return -1;
    }
    if (s_attr_to_type_tbl[attr] != _PARSE_TYPE_INTEGER)
    {
        sh_echo(s_sh_hdl, "待设置的参数类型不是带符号整数\r\n");
        return -1;
    }

    if (argv[0] == NULL || *argv[0] == '\0')
    {
        sh_echo(s_sh_hdl, "缺少参数\r\n");
        return -1;
    }

    if (strcmp(argv[0], "?") == 0)
    {
        if (high < low)
        {
            low ^= high;
            high ^= low;
            low ^= high;
        }
        sh_echo(s_sh_hdl, "有效范围: %d .. %d\r\n", low, high);
        sh_echo(s_sh_hdl, "当前值:   %d\r\n", _get_integer(dest, attr));
        return 0;
    }

    sh_parse_t pv = sh_parse_value(argv[0]);
    switch (pv.type)
    {
    case _PARSE_TYPE_INTEGER: // 解析出的参数格式是带符号整型
        return _set_dest_integer(dest, attr, cb, pv.value.val_integer, low, high);

    case _PARSE_TYPE_UNSIGNED: // 解析出的参数格式是无符号整型
        if (pv.value.val_unsigned > (1u << (sizeof(pv.value.val_unsigned) * 8 - 1)) - 1)
        {
            sh_echo(s_sh_hdl, "参数 %u 溢出\r\n", pv.value.val_unsigned);
            return -1;
        }
        return _set_dest_integer(dest, attr, cb, pv.value.val_unsigned, low, high);

    default:
        sh_echo(s_sh_hdl, "参数 '%s' 格式错误, 请输入整数\r\n", argv[0]);
        return -1;
    }
}

int vset_float(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], float low, float high)
{
    SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
    SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
    SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_FLOAT, "待设置的参数类型不是浮点数");

    if (s_sh_hdl == NULL)
    {
        return -1;
    }
    if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
    {
        sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
        return -1;
    }
    if (s_attr_to_type_tbl[attr] != _PARSE_TYPE_FLOAT)
    {
        sh_echo(s_sh_hdl, "待设置的参数类型不是浮点数\r\n");
        return -1;
    }

    if (argv[0] == NULL || *argv[0] == '\0')
    {
        sh_echo(s_sh_hdl, "缺少参数\r\n");
        return -1;
    }

    if (strcmp(argv[0], "?") == 0)
    {
        if (high < low)
        {
            float tmp = low;
            low = high;
            high = tmp;
        }
        sh_echo(s_sh_hdl, "有效范围: %f .. %f\r\n", low, high);
        sh_echo(s_sh_hdl, "当前值:   %f\r\n", _get_float(dest, attr));
        return 0;
    }

    sh_parse_t pv = sh_parse_value(argv[0]);
    switch (pv.type)
    {
    case _PARSE_TYPE_INTEGER: // 解析出的参数格式是带符号整型
        return _set_dest_float(dest, attr, cb, pv.value.val_integer, low, high);

    case _PARSE_TYPE_UNSIGNED: // 解析出的参数格式是无符号整型
        return _set_dest_float(dest, attr, cb, pv.value.val_unsigned, low, high);

    case _PARSE_TYPE_FLOAT: // 解析出的参数格式是浮点数
        return _set_dest_float(dest, attr, cb, pv.value.val_float, low, high);

    default:
        sh_echo(s_sh_hdl, "参数 '%s' 格式错误, 请输入数值\r\n", argv[0]);
        return -1;
    }
}

int vset_str(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], unsigned bufsize)
{
    SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
    SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
    SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_STRING, "待设置的参数类型不是字符串");

    if (s_sh_hdl == NULL)
    {
        return -1;
    }
    if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
    {
        sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
        return -1;
    }
    if (s_attr_to_type_tbl[attr] != _PARSE_TYPE_STRING)
    {
        sh_echo(s_sh_hdl, "待设置的参数类型不是字符串\r\n");
        return -1;
    }

    if (argv[0] == NULL || *argv[0] == '\0')
    {
        sh_echo(s_sh_hdl, "缺少参数\r\n");
        return -1;
    }

    if (strcmp(argv[0], "?") == 0)
    {
        sh_echo(s_sh_hdl, "最大长度: %d\r\n", bufsize - 1);
        sh_echo(s_sh_hdl, "当前值:   %s\r\n", _get_string(dest, attr));
        return 0;
    }

    if (argv[1] && *argv[1] != '\0')
    {
        sh_echo(s_sh_hdl, "参数中有空格。如果目标设备名中包含空格，请使用引号表示\r\n");
        return -1;
    }

    return _set_dest_string(dest, attr, cb, argv[0], bufsize);
}

int vset_enum(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], const char *enum_str)
{
    SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
    SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");

    if (s_sh_hdl == NULL)
    {
        return -1;
    }
    if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
    {
        sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
        return -1;
    }

    if (argv[0] == NULL || *argv[0] == '\0')
    {
        sh_echo(s_sh_hdl, "缺少参数\r\n");
        return -1;
    }

    /* 格式化 enum_str 到 enum_buf */
    char enum_buf[CONFIG_SH_MAX_LINE_LEN];
    int enum_len = _enum_format(enum_buf, __ARR_SIZE(enum_buf), enum_str);
    if (enum_len < 0)
    {
        return -1;
    }

    char *match_key = NULL;
    char *match_value = NULL;
    int type_flag = 0;

    if (strcmp(argv[0], "?") == 0)
    {
        sh_echo(s_sh_hdl, "可选值:\r\n");
        _get_enum_by_param(dest, attr, &match_key, &match_value, enum_buf, true, false);
        if (match_value)
        {
            sh_echo(s_sh_hdl, "当前值:\t%s\r\n", match_key);
        }
        return 0;
    }

    type_flag = _get_enum_by_key(argv[0], &match_value, enum_buf);
    if (type_flag == 0)
    {
        sh_echo(s_sh_hdl, "选项为空\r\n");
        return -1;
    }
    if (match_value == NULL)
    {
        sh_echo(s_sh_hdl, "'%s': 非法的取值\r\n", argv[0]);
        return -1;
    }

    return _set_dest_enum(dest, attr, cb, match_value, type_flag);
}

void vset_cp_enum(int argc, bool flag, const char *enum_str)
{
    if (argc + flag == 1)
    {
        if (enum_str != NULL)
        {
            SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");

            if (s_sh_hdl == NULL)
            {
                return;
            }

            /* 格式化 enum_str 到 enum_buf */
            char enum_buf[CONFIG_SH_MAX_LINE_LEN];
            int enum_len = _enum_format(enum_buf, __ARR_SIZE(enum_buf), enum_str);
            if (enum_len < 0)
            {
                return;
            }

            /* 分割字符串 str_buf 并穷举匹配到的值，输出 match_key, match_value, type_flag */
            char *match_key = NULL;
            char *match_value = NULL;
            _get_enum_by_param(enum_buf, __GENERIC_ATTR(enum_buf), &match_key, &match_value, enum_buf, false, true);
        }
        else
        {
            sh_completion_resource(s_sh_hdl, NULL, "? ", NULL);
        }
    }
}

/**
 * @brief 内部函数，由 vset_option_cp() 专用，测试前正在输入的参数有对应存在的候选选项
 *
 * @param input     当前正在输入的参数
 * @param p         选项描述结构体
 * @param size      选项描述结构体的长度
 * @retval true 当前正在输入的参数存在于候选选项中
 * @retval false 当前正在输入的参数不在候选选项中
 */
static bool _is_in_option(const char *input, const sh_vset_param_t *p, unsigned size)
{
    int len = strlen(input);
    for (int i = 0; i < size / sizeof(*p); i++)
    {
        if (strncmp(input, p[i].option, len) == 0)
        {
            return true;
        }
    }
    return false;
}

/**
 * @brief 内部函数，由 vset_option_cp() 专用，查找输入的参数的对应选项
 * @brief
 *
 * @param input
 * @param p
 * @param size
 * @return const sh_vset_param_t*
 */
static const sh_vset_param_t *_find_option(const char *input, const sh_vset_param_t *p, unsigned size)
{
    for (int i = 0; i < size / sizeof(*p); i++)
    {
        if (strcmp(input, p[i].option) == 0)
        {
            return &p[i];
        }
    }
    return NULL;
}

/**
 * @brief 内部函数，由 vset_option_cp() 专用，执行对选项的补全
 *
 * @param sh_hdl    原参数
 * @param argc      原参数
 * @param argv      原参数指针值，可能被更新
 * @param p         选项描述结构体
 * @param size      选项描述结构体的长度
 * @retval true
 */
static bool _do_completing_option(sh_t *sh_hdl, int argc, const char *argv[], const sh_vset_param_t *p, unsigned size)
{
    bool ret = false;

    for (int i = 0; i < size / sizeof(*p); i++) // 遍历 p[i].option 分析
    {
        /* 遍历已输入的参数确认当前的 p[i].option 未曾出现过 */
        bool repeat_flag = false;
        for (int j = 0; j < argc - 1; j++)
        {
            if (strcmp(p[i].option, argv[j]) == 0)
            {
                repeat_flag = true;
                break;
            }
        }

        if (repeat_flag == false)
        {
            /* 执行 sh_completion_resource() */
            char option_cpy[0x100];
            int len = 0;
            for (len = 0; len < sizeof(option_cpy) - 2; len++)
            {
                option_cpy[len] = p[i].option[len];
                if (option_cpy[len] == '\0')
                {
                    break;
                }
            }
            option_cpy[len++] = ' ';
            option_cpy[len] = '\0';
            sh_completion_resource(sh_hdl, NULL, option_cpy, p[i].help);
            ret = true;
        }
    }

    return ret;
}

/**
 * @brief 内部函数，由 vset_option_cp() 专用，执行对 SET_ENUM 中的 ENUM_STR 的补全
 *
 * @param option    已知的选项
 * @param p         选项描述结构体
 * @param size      选项描述结构体的长度
 */
static bool _do_completing_enum(const char *option, const sh_vset_param_t *p, unsigned size)
{
    /* 根据上一个参数，遍历 p 找到对应的成员 */
    if (option)
    {
        for (int i = 0; i < size / sizeof(*p); i++)
        {
            if (strcmp(option, p[i].option) == 0)
            {
                if (p[i].set_func)
                {
                    vset_cp_enum(1, false, p[i].enum_str);
                }

                return true;
            }
        }
    }

    return false;
}

static int _set_dest_unsigned(void *dest, __type_attr_t attr, vset_cb cb, unsigned int value, unsigned int low, unsigned int high)
{
    vset_global_cb global_cb = NULL;
    int ret = -1;

    SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
    SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_UNSIGNED, "待设置的参数类型不是正整数");

    if (value < low)
    {
        sh_echo(s_sh_hdl, "设置失败: %d < %d(min)\r\n", value, low);
        return -1;
    }

    if (value > high)
    {
        sh_echo(s_sh_hdl, "设置失败: %d > %d(max)\r\n", value, high);
        return -1;
    }

    switch (attr)
    {
    case __TYPE_ATTR_U8:
    {
        SYS_ASSERT((low & (~0u << 8)) == 0 && (high & (~0u << 8)) == 0, "范围值溢出");
        if ((low & (~0u << 8)) || (high & (~0u << 8)))
        {
            sh_echo(s_sh_hdl, "设置失败: 设置值溢出\r\n");
            return -1;
        }
        if (*((uint8_t *)dest) != value)
        {
            _PARAM_CB();
            *((uint8_t *)dest) = value;
            global_cb = s_global_cb;
        }
        ret = 0;
        break;
    }

    case __TYPE_ATTR_U16:
    {
        SYS_ASSERT((low & (~0u << 16)) == 0 && (high & (~0u << 16)) == 0, "范围值溢出");
        if ((low & (~0u << 16)) || (high & (~0u << 16)))
        {
            sh_echo(s_sh_hdl, "设置失败: 设置值溢出\r\n");
            return -1;
        }
        if (*((uint16_t *)dest) != value)
        {
            _PARAM_CB();
            *((uint16_t *)dest) = value;
            global_cb = s_global_cb;
        }
        ret = 0;
        break;
    }

    case __TYPE_ATTR_U32:
    {
        if (*((uint32_t *)dest) != value)
        {
            _PARAM_CB();
            *((uint32_t *)dest) = value;
            global_cb = s_global_cb;
        }
        ret = 0;
        break;
    }

    case __TYPE_ATTR_U64:
    {
        if (*((uint64_t *)dest) != value)
        {
            _PARAM_CB();
            *((uint64_t *)dest) = value;
            global_cb = s_global_cb;
        }
        ret = 0;
        break;
    }

    default:
        return -1;
    }

    if (global_cb)
    {
        global_cb(s_sh_hdl);
    }
    return ret;
}

static int _set_dest_integer(void *dest, __type_attr_t attr, vset_cb cb, signed int value, signed int low, signed int high)
{
#define _MAX_S8 127
#define _MIN_S8 -128
#define _MAX_S16 32767
#define _MIN_S16 -32768

    vset_global_cb global_cb = NULL;
    int ret = -1;

    SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
    SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_INTEGER, "待设置的参数类型不是带符号整数");

    if (value < low)
    {
        sh_echo(s_sh_hdl, "设置失败: %d < %d(min)\r\n", value, low);
        return -1;
    }

    if (value > high)
    {
        sh_echo(s_sh_hdl, "设置失败: %d > %d(max)\r\n", value, high);
        return -1;
    }

    switch (attr)
    {
    case __TYPE_ATTR_CHR:
    {
        char data = value;
        if (data != value)
        {
            sh_echo(s_sh_hdl, "设置失败: 设置值溢出\r\n");
            return -1;
        }
        if (*((char *)dest) != data)
        {
            _PARAM_CB();
            *((char *)dest) = data;
            global_cb = s_global_cb;
        }
        ret = 0;
        break;
    }

    case __TYPE_ATTR_BOOL:
    {
        bool data = value;
        if (data != value)
        {
            sh_echo(s_sh_hdl, "设置失败: 设置值溢出\r\n");
            return -1;
        }
        if (*((bool *)dest) != data)
        {
            _PARAM_CB();
            *((bool *)dest) = data;
            global_cb = s_global_cb;
        }
        ret = 0;
        break;
    }

    case __TYPE_ATTR_S8:
    {
        SYS_ASSERT(low >= _MIN_S8 && low <= _MAX_S8, "范围值溢出");
        SYS_ASSERT(high >= _MIN_S8 && high <= _MAX_S8, "范围值溢出");
        if (low < _MIN_S8 || low > _MAX_S8 ||
            high < _MIN_S8 || high > _MAX_S8)
        {
            sh_echo(s_sh_hdl, "设置失败: 设置值溢出\r\n");
            return -1;
        }
        if (*((int8_t *)dest) != value)
        {
            _PARAM_CB();
            *((int8_t *)dest) = value;
            global_cb = s_global_cb;
        }
        ret = 0;
        break;
    }

    case __TYPE_ATTR_S16:
    {
        SYS_ASSERT(low >= _MIN_S16 && low <= _MAX_S16, "范围值溢出");
        SYS_ASSERT(high >= _MIN_S16 && high <= _MAX_S16, "范围值溢出");
        if (low < _MIN_S16 || low > _MAX_S16 ||
            high < _MIN_S16 || high > _MAX_S16)
        {
            sh_echo(s_sh_hdl, "设置失败: 设置值溢出\r\n");
            return -1;
        }
        if (*((int16_t *)dest) != value)
        {
            _PARAM_CB();
            *((int16_t *)dest) = value;
            global_cb = s_global_cb;
        }
        ret = 0;
        break;
    }

    case __TYPE_ATTR_S32:
    {
        if (*((int32_t *)dest) != value)
        {
            _PARAM_CB();
            *((int32_t *)dest) = value;
            global_cb = s_global_cb;
        }
        ret = 0;
        break;
    }

    case __TYPE_ATTR_S64:
    {
        if (*((int64_t *)dest) != value)
        {
            _PARAM_CB();
            *((int64_t *)dest) = value;
            global_cb = s_global_cb;
        }
        ret = 0;
        break;
    }

    default:
        return -1;
    }

    if (global_cb)
    {
        global_cb(s_sh_hdl);
    }
    return ret;
}

static int _set_dest_float(void *dest, __type_attr_t attr, vset_cb cb, float value, float low, float high)
{
    vset_global_cb global_cb = NULL;
    int ret = -1;

    SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
    SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_FLOAT, "待设置的参数类型不是浮点数");

    if (value < low)
    {
        sh_echo(s_sh_hdl, "设置失败: %f < %f(min)\r\n", value, low);
        return -1;
    }

    if (value > high)
    {
        sh_echo(s_sh_hdl, "设置失败: %f > %f(max)\r\n", value, high);
        return -1;
    }

    switch (attr)
    {
    case __TYPE_ATTR_FLOAT:
    {
        if (*((float *)dest) != value)
        {
            _PARAM_CB();
            *((float *)dest) = value;
            global_cb = s_global_cb;
        }
        ret = 0;
        break;
    }
    case __TYPE_ATTR_DOUBLE:
    {
        if (*((double *)dest) != value)
        {
            _PARAM_CB();
            *((double *)dest) = value;
            global_cb = s_global_cb;
        }
        ret = 0;
        break;
    }

    default:
        return -1;
    }

    if (global_cb)
    {
        global_cb(s_sh_hdl);
    }
    return ret;
}

static int _set_dest_string(void *dest, __type_attr_t attr, vset_cb cb, const char *str, unsigned bufsize)
{
    int str_size = strlen(str) + 1;
    vset_global_cb global_cb = NULL;
    int ret = -1;

    SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
    SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_STRING, "待设置的参数类型不是字符串");

    if (str_size > bufsize)
    {
        sh_echo(s_sh_hdl, "注意: '%s' 大于最大长度 %d\r\n", str, bufsize - 1);
        str_size = bufsize;
    }

    switch (attr)
    {
    case __TYPE_ATTR_STR:
        if (memcmp(dest, str, str_size))
        {
            if (cb)
            {
                char value[str_size + 1];
                memset(value, 0, str_size + 1);
                memcpy(value, str, str_size);
                _PARAM_CB();
            }
            memset(dest, 0, bufsize);
            memcpy(dest, str, str_size);
            global_cb = s_global_cb;
        }
        ret = 0;
        break;

    default:
        return -1;
    }

    if (global_cb)
    {
        global_cb(s_sh_hdl);
    }
    return ret;
}

static int _set_dest_enum(void *dest, __type_attr_t attr, vset_cb cb, const char *value, int type_flag)
{
    sh_parse_t pv = sh_parse_value(value);
    switch (s_attr_to_type_tbl[attr])
    {
    case _PARSE_TYPE_UNSIGNED: // 待设置的参数格式是无符号整型
    {
        if (type_flag & (_TYPE_FLAG_INTEGER | _TYPE_FLAG_FLOAT | _TYPE_FLAG_STRING))
        {
            sh_echo(s_sh_hdl, "ENUM_STR 格式错误, 包含非法的 value 类型\r\n");
            return -1;
        }
        switch (pv.type)
        {
        case _PARSE_TYPE_UNSIGNED: // 当前匹配的参数格式是无符号整型
            return _set_dest_unsigned(dest, attr, cb, pv.value.val_unsigned, pv.value.val_unsigned, pv.value.val_unsigned);

        default:
            return -1;
        }
    }
    break;

    case _PARSE_TYPE_INTEGER: // 待设置的参数格式是带符号整型
    {
        if (type_flag & (_TYPE_FLAG_FLOAT | _TYPE_FLAG_STRING))
        {
            sh_echo(s_sh_hdl, "ENUM_STR 格式错误, 包含非法的 value 类型\r\n");
            return -1;
        }
        switch (pv.type)
        {
        case _PARSE_TYPE_INTEGER: // 当前匹配的参数格式是带符号整型
            return _set_dest_integer(dest, attr, cb, pv.value.val_integer, pv.value.val_integer, pv.value.val_integer);

        case _PARSE_TYPE_UNSIGNED: // 当前匹配的参数格式是无符号整型
            return _set_dest_integer(dest, attr, cb, pv.value.val_unsigned, pv.value.val_unsigned, pv.value.val_unsigned);

        default:
            return -1;
        }
    }
    break;

    case _PARSE_TYPE_FLOAT: // 待设置的参数格式是浮点数
    {
        if (type_flag & (_TYPE_FLAG_STRING))
        {
            sh_echo(s_sh_hdl, "ENUM_STR 格式错误, 包含非法的 value 类型\r\n");
            return -1;
        }
        switch (pv.type)
        {
        case _PARSE_TYPE_INTEGER: // 当前匹配的参数格式是带符号整型
            return _set_dest_float(dest, attr, cb, pv.value.val_integer, pv.value.val_integer, pv.value.val_integer);

        case _PARSE_TYPE_UNSIGNED: // 当前匹配的参数格式是无符号整型
            return _set_dest_float(dest, attr, cb, pv.value.val_unsigned, pv.value.val_unsigned, pv.value.val_unsigned);

        case _PARSE_TYPE_FLOAT: // 当前匹配的参数格式是浮点数
            return _set_dest_float(dest, attr, cb, pv.value.val_float, pv.value.val_float, pv.value.val_float);

        default:
            return -1;
        }
    }
    break;

    case _PARSE_TYPE_STRING: // 待设置的参数格式是字符串
    {
        return _set_dest_string(dest, attr, cb, value, strlen(value) + 1);
    }
    break;

    default:
        sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
        return -1;
    }

    return -1;
}

static signed int _get_integer(void *dest, __type_attr_t attr)
{
    SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
    SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
    SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_INTEGER, "待设置的参数类型不是带符号整数");

    switch (attr)
    {
    case __TYPE_ATTR_CHR:
        return *((char *)dest);

    case __TYPE_ATTR_BOOL:
        return *((bool *)dest);

    case __TYPE_ATTR_S8:
        return *((int8_t *)dest);

    case __TYPE_ATTR_S16:
        return *((int16_t *)dest);

    case __TYPE_ATTR_S32:
        return *((int32_t *)dest);

    case __TYPE_ATTR_S64:
        return *((int64_t *)dest);

    default:
        return -1;
    }
}

static float _get_float(void *dest, __type_attr_t attr)
{
    SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
    SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
    SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_FLOAT, "待设置的参数类型不是浮点数");

    switch (attr)
    {
    case __TYPE_ATTR_FLOAT:
        return *((float *)dest);

    case __TYPE_ATTR_DOUBLE:
        return *((double *)dest);

    default:
        return -1;
    }
}

static char *_get_string(void *dest, __type_attr_t attr)
{
    SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
    SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
    SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_STRING, "待设置的参数类型不是字符串");

    return dest;
}

static unsigned int _get_unsigned(void *dest, __type_attr_t attr)
{
    SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
    SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
    SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_UNSIGNED, "待设置的参数类型不是正整数");

    switch (attr)
    {
    case __TYPE_ATTR_U8:
        return *((uint8_t *)dest);

    case __TYPE_ATTR_U16:
        return *((uint16_t *)dest);

    case __TYPE_ATTR_U32:
        return *((uint32_t *)dest);

    case __TYPE_ATTR_U64:
        return *((uint64_t *)dest);

    default:
        return -1;
    }
}

/**
 * @brief 格式化原始的 enum_str 并输出到  enum_buf
 *
 * @param enum_buf[out] 复制 enum_str 并格式化的需要的缓存
 * @param buf_len       enum_buf 的长度
 * @param enum_str      原始的选项格式
 * @retval < 0 表示 enum_str 的格式错误(键值或数值不能包含空格)
 * @retval >= 0 表示输出的 enum_buf 中的字符数（不包含 '\0'）
 */
static int _enum_format(char *enum_buf, int buf_len, const char *enum_str)
{
    /* 复制 enum_str 到 str_buf 并移除空格 */
    if (strlen(enum_str) >= buf_len)
    {
        sh_echo(s_sh_hdl, "注意: str_buff 长度不足\r\n");
    }
    strncpy(enum_buf, enum_str, buf_len - 1);
    enum_buf[buf_len - 1] = '\0';

    /* 去除可能的多余空格 */
    buf_len = strlen(enum_buf);
    int cid = 0;
    int flag1 = 0;
    int flag2 = 1;
    for (int i = 0; i < buf_len; i++)
    {
        if (enum_buf[i] > ' ')
        {
            enum_buf[cid] = enum_str[i];
            cid++;

            if (enum_buf[i] != ',' && enum_buf[i] != '=')
            {
                flag1 += flag2;
                flag1 += !flag1;
                if (flag1 > 1)
                {
                    break;
                }
            }
            else
            {
                flag1 = 0;
            }
            flag2 = 0;
        }
        else
        {
            flag2 = 1;
        }
    }
    if (flag1 > 1)
    {
        sh_echo(s_sh_hdl, "ENUM_STR 格式错误, 键值或数值不能包含空格\r\n");
        return -1;
    }

    enum_buf[cid] = '\0';
    return cid; // 返回字符串长度（不包含结束符）
}

/**
 * @brief 根据给出的 key 在 enum_buf 查找对应的 value
 *
 * @param key               给出的被搜索的 key
 * @param match_value[out]  与 key 中的值完全匹配的 value 位置，该位置在 enum_buf 中，如果结果为 NULL 表示在 enum_buf 中不存在与 param 的值完全匹配的项
 * @param enum_buf          通过 _enum_format() 格式化的缓存
 * @retval int 按位表示在 enum_buf 中出现过的 value 的数据类型。
 *      _TYPE_FLAG_UNSIGNED     掩码表示在 enum_buf 中包含无符号整型
 *      _TYPE_FLAG_INTEGER      掩码表示在 enum_buf 中包含有符号整型
 *      _TYPE_FLAG_FLOAT        掩码表示在 enum_buf 中包含浮点数
 *      _TYPE_FLAG_STRING       掩码表示在 enum_buf 中包含字符串
 */
static int _get_enum_by_key(const char *key, char **match_value, char *enum_buf)
{
    int type_flag = 0; // 在 match_value 中出现过的数据类型

    /* 分割字符串 enum_buf 并穷举匹配到的值 */
    *match_value = NULL;
    char *save_token;
    char *token = strtok_r(enum_buf, ",", &save_token);
    while (token)
    {
        char *enum_value;
        char *enum_key = strtok_r(token, "=", &enum_value);

        if (enum_key == NULL || *enum_key == '\0' || *enum_value == '\0')
        {
            sh_echo(s_sh_hdl, "'%s' 的格式错误, 请使用如下格式表示: 'key1=value,key2=value,...'\r\n", token);
            return 0;
        }

        sh_parse_t pv = sh_parse_value(enum_value);
        switch (pv.type)
        {
        case _PARSE_TYPE_INTEGER: // 解析出的参数格式是带符号整型
            type_flag |= _TYPE_FLAG_INTEGER;
            break;

        case _PARSE_TYPE_UNSIGNED: // 解析出的参数格式是无符号整型
            type_flag |= _TYPE_FLAG_UNSIGNED;
            break;

        case _PARSE_TYPE_FLOAT: // 解析出的参数格式是浮点数
            type_flag |= _TYPE_FLAG_FLOAT;
            break;

        case _PARSE_TYPE_STRING: // 解析出的参数格式是字符串
            type_flag |= _TYPE_FLAG_STRING;
            break;

        default:
            break;
        }

        if (*match_value == NULL)
        {
            if (strcmp(enum_key, key) == 0)
            {
                *match_value = enum_value;
            }
        }

        token = strtok_r(NULL, ",", &save_token);
    }

    return type_flag;
}

/**
 * @brief 根据给出的 param 在 enum_buf 查找对应的 key 和 value
 * 1. 分析 enum_buf 中存在的所有 value 项的数据类型并作为返回值
 * 2. 根据 param 的值，在格式化数据中搜索与该值完全匹配的 key 和 value 并输出到 *match_key 和 *match_value
 * 2. 可选打印 enum_buf 中的 key 和 value
 *
 * @param param             指向待设置的变量属性的结构体
 * @param match_key[out]    与 param 中的值完全匹配的 key 位置，该位置在 enum_buf 中，如果结果为 NULL 表示在 enum_buf 中不存在与 param 的值完全匹配的项
 * @param match_value[out]  与 param 中的值完全匹配的 value 位置，该位置在 enum_buf 中，如果结果为 NULL 表示在 enum_buf 中不存在与 param 的值完全匹配的项
 * @param enum_buf          通过 _enum_format() 格式化的缓存
 * @param print_list        是否打印所有 enum_buf 中的项目
 * @param print_cp          是否执行自动补全
 * @retval int 按位表示在 enum_buf 中出现过的 value 的数据类型。
 *      _TYPE_FLAG_UNSIGNED     掩码表示在 enum_buf 中包含无符号整型
 *      _TYPE_FLAG_INTEGER      掩码表示在 enum_buf 中包含有符号整型
 *      _TYPE_FLAG_FLOAT        掩码表示在 enum_buf 中包含浮点数
 *      _TYPE_FLAG_STRING       掩码表示在 enum_buf 中包含字符串
 */
static int _get_enum_by_param(void *dest, __type_attr_t attr, char **match_key, char **match_value, char *enum_buf, bool print_list, bool print_cp)
{
    char param_value_str[0x100];
    int type_flag = 0; // 在 match_value 中出现过的数据类型

    if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
    {
        sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
        return -1;
    }

    switch (s_attr_to_type_tbl[attr])
    {
    case _PARSE_TYPE_INTEGER: // 待设置的参数格式是带符号整型
        SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%d", _get_integer(dest, attr));
        break;

    case _PARSE_TYPE_UNSIGNED: // 待设置的参数格式是无符号整型
        SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%u", _get_unsigned(dest, attr));
        break;

    case _PARSE_TYPE_FLOAT: // 待设置的参数格式是浮点数
        SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%f", _get_float(dest, attr));
        break;

    case _PARSE_TYPE_STRING: // 待设置的参数格式是字符串
        SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%s", _get_string(dest, attr));
        break;

    default:
        sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
        return -1;
    }
    param_value_str[__ARR_SIZE(param_value_str) - 1] = '\0';

    /* 分割字符串 enum_buf 并穷举匹配到的值 */
    *match_key = NULL;
    *match_value = NULL;
    char *save_token;
    char *token = strtok_r(enum_buf, ",", &save_token);
    while (token)
    {
        char *enum_value;
        char *enum_key = strtok_r(token, "=", &enum_value);
        char key_value_str[__ARR_SIZE(param_value_str)];

        if (*enum_key == '\0' || *enum_value == '\0')
        {
            sh_echo(s_sh_hdl, "'%s' 的格式错误, 请使用如下格式表示: 'key1=value,key2=value,...'\r\n", enum_key);
            return 0;
        }

        key_value_str[0] = '\0';
        sh_parse_t pv = sh_parse_value(enum_value);
        switch (pv.type)
        {
        case _PARSE_TYPE_UNSIGNED: // 解析出的参数格式是无符号整型
            type_flag |= _TYPE_FLAG_UNSIGNED;
            if (*match_key == NULL)
            {
                switch (s_attr_to_type_tbl[attr])
                {
                case _PARSE_TYPE_UNSIGNED: // 待设置的参数格式是无符号整型
                    SYS_SNPRINT(key_value_str, sizeof(key_value_str), "%u", pv.value.val_unsigned);
                    break;
                case _PARSE_TYPE_INTEGER: // 待设置的参数格式是带符号整型
                    SYS_SNPRINT(key_value_str, sizeof(key_value_str), "%d", pv.value.val_unsigned);
                    break;
                case _PARSE_TYPE_FLOAT: // 待设置的参数格式是浮点数
                    SYS_SNPRINT(key_value_str, sizeof(key_value_str), "%f", (float)pv.value.val_unsigned);
                    break;
                case _PARSE_TYPE_STRING: // 待设置的参数格式是字符串
                    SYS_SNPRINT(key_value_str, sizeof(key_value_str), "%s", enum_value);
                    break;
                default:
                    break;
                }
            }
            break;

        case _PARSE_TYPE_INTEGER: // 解析出的参数格式是带符号整型
            type_flag |= _TYPE_FLAG_INTEGER;
            if (*match_key == NULL)
            {
                switch (s_attr_to_type_tbl[attr])
                {
                case _PARSE_TYPE_INTEGER: // 待设置的参数格式是带符号整型
                    SYS_SNPRINT(key_value_str, sizeof(key_value_str), "%d", pv.value.val_integer);
                    break;
                case _PARSE_TYPE_FLOAT: // 待设置的参数格式是浮点数
                    SYS_SNPRINT(key_value_str, sizeof(key_value_str), "%f", (float)pv.value.val_integer);
                    break;
                case _PARSE_TYPE_STRING: // 待设置的参数格式是字符串
                    SYS_SNPRINT(key_value_str, sizeof(key_value_str), "%s", enum_value);
                    break;
                default:
                    break;
                }
            }
            break;

        case _PARSE_TYPE_FLOAT: // 解析出的参数格式是浮点数
            type_flag |= _TYPE_FLAG_FLOAT;
            if (*match_key == NULL)
            {
                switch (s_attr_to_type_tbl[attr])
                {
                case _PARSE_TYPE_FLOAT: // 待设置的参数格式是浮点数
                    SYS_SNPRINT(key_value_str, sizeof(key_value_str), "%f", (float)pv.value.val_float);
                    break;
                case _PARSE_TYPE_STRING: // 待设置的参数格式是字符串
                    SYS_SNPRINT(key_value_str, sizeof(key_value_str), "%s", enum_value);
                    break;
                default:
                    break;
                }
            }
            break;

        case _PARSE_TYPE_STRING: // 解析出的参数格式是字符串
            type_flag |= _TYPE_FLAG_STRING;
            if (*match_key == NULL)
                SYS_SNPRINT(key_value_str, sizeof(key_value_str), "%s", enum_value);
            break;

        default:
            break;
        }

        if (*match_key == NULL)
        {
            if (strcmp(key_value_str, param_value_str) == 0)
            {
                *match_key = enum_key;
                *match_value = enum_value;
            }
        }

        if (print_list)
        {
            sh_echo(s_sh_hdl, "\t%s (%s)\r\n", enum_key, enum_value);
        }

        if (print_cp)
        {
            char key_cpy[0x100];
            int len = 0;
            for (len = 0; len < sizeof(key_cpy) - 2; len++)
            {
                key_cpy[len] = enum_key[len];
                if (key_cpy[len] == '\0')
                {
                    break;
                }
            }
            key_cpy[len++] = ' ';
            key_cpy[len] = '\0';
            sh_completion_resource(s_sh_hdl, NULL, key_cpy, NULL);
        }

        token = strtok_r(NULL, ",", &save_token);
    }

    switch (s_attr_to_type_tbl[attr])
    {
    case _PARSE_TYPE_UNSIGNED: // 待设置的参数格式是无符号整型
    {
        if (type_flag & (_TYPE_FLAG_INTEGER | _TYPE_FLAG_FLOAT | _TYPE_FLAG_STRING))
        {
            sh_echo(s_sh_hdl, "ENUM_STR 格式错误, 包含非法的 value 类型\r\n");
            return -1;
        }
    }
    break;

    case _PARSE_TYPE_INTEGER: // 待设置的参数格式是带符号整型
    {
        if (type_flag & (_TYPE_FLAG_FLOAT | _TYPE_FLAG_STRING))
        {
            sh_echo(s_sh_hdl, "ENUM_STR 格式错误, 包含非法的 value 类型\r\n");
            return -1;
        }
    }
    break;

    case _PARSE_TYPE_FLOAT: // 待设置的参数格式是浮点数
    {
        if (type_flag & (_TYPE_FLAG_STRING))
        {
            sh_echo(s_sh_hdl, "ENUM_STR 格式错误, 包含非法的 value 类型\r\n");
            return -1;
        }
    }
    break;

    default:
        break;
    }

    return type_flag;
}
