/**
 * @file    myFunc.h
 * @brief   基础工具函数接口 — 65 个函数，7 大分类
 * @details 校验计算 / 字符串转换 / 时间处理 / 文件目录操作 /
 *          进程管理 / 环境变量路径 / IPC 消息队列
 */

#ifndef _MY_FUNC_H_
#define _MY_FUNC_H_
#include <stdint.h>
#include <time.h>
#include <sys/time.h>
#ifdef __cplusplus
extern "C"
{
#endif

/**
 * @brief 系统时间结构体（位域存储，用于嵌入式装置内部表示）
 * @note  year: 7bit(0-127+1900), month:4bit(1-12), day:5bit(1-31)
 *        hour:5bit(0-23), min:6bit(0-59), ms:16bit(0-59999)
 */
typedef struct
{
	uint32_t ms  : 16;   /* 毫秒（实际存储秒*1000+毫秒，范围 0-59999） */
	uint32_t min : 6;    /* 分钟 0-59 */
	uint32_t     : 2;    /* 保留 */
	uint32_t hour: 5;    /* 小时 0-23 */
	uint32_t     : 3;    /* 保留 */
	uint32_t day : 5;    /* 日期 1-31 */
	uint32_t week: 3;    /* 星期 */
	uint32_t month:4;    /* 月份 1-12 */
	uint32_t     : 4;    /* 保留 */
	uint32_t year: 7;    /* 年份偏移(实际值-1900)，范围 0-127 */
	uint32_t     : 1;    /* 保留 */
} stru_time_sys;

/**
 * @brief 日历时间结构体（Unix 时间 + 微秒）
 */
typedef struct
{
	time_t sec;          /* Unix 时间戳（秒） */
	time_t usec;         /* 微秒部分 */
} stru_time_cal;

/**
 * @brief IPC 消息文本载荷
 */
typedef struct
{
	int  qid;            /* 响应队列 ID */
	int  type;           /* 响应类型（enum_ipc_resp） */
	int  len;            /* 有效数据长度 */
	char text[4096];     /* 消息内容 */
} stru_ipc_text;

/**
 * @brief IPC 响应类型
 */
typedef enum
{
	IPC_RESP_NONE   = 1, /* 无需响应 */
	IPC_RESP_ONCE,       /* 单次响应 */
	IPC_RESP_ALWAYS      /* 持续响应 */
} enum_ipc_resp;

/**
 * @brief IPC 消息（System V 消息队列格式）
 */
typedef struct
{
	long          id;    /* 消息类型 ID */
	stru_ipc_text t;     /* 消息载荷 */
} stru_ipc_msg;

/**
 * @brief 文件描述头结构（256 字节，含 CRC 校验）
 * @note  flag 魔数为 0xA55AA55AA55AA55A
 */
#pragma pack(1)
typedef struct
{
	uint64_t flag;       /* 魔数标识 0xA55AA55AA55AA55A */
	char     ver[16];    /* 版本号 */
	char     author[16]; /* 作者 */
	char     modify[32]; /* 修改时间 YYYY-MM-DD HH-MM-SS */
	uint16_t crc;        /* CRC16 校验 */
	char     desc[128];  /* 附加描述 */
	char     bak[54];    /* 对齐填充（总计 256 字节） */
} stru_file_info;
#pragma pack()

/* ================================================================
 * 校验计算函数（CRC16 使用 Modbus 多项式 0xA001）
 * ================================================================ */

/** 8 位累加校验和 */
uint8_t  func_cal_sum_byte(const uint8_t *d, uint32_t n);

/** 16 位累加校验和 */
uint16_t func_cal_sum_word(const uint8_t *d, uint32_t n);

/** CRC16（Modbus 多项式，初始值 0xFFFF） */
uint16_t func_cal_crc16(const uint8_t *d, uint32_t n);

/** CRC32（标准多项式，初始值 0xFFFFFFFF） */
uint32_t func_cal_crc32(const uint8_t *d, uint32_t n);

/** 文件 CRC16（4KB 缓冲区流式计算） */
uint16_t func_cal_file_crc16(const char *path);

/** 文件 CRC32（4KB 缓冲区流式计算） */
uint32_t func_cal_file_crc32(const char *path);

/* ================================================================
 * 字符串转换函数
 * ================================================================ */

/** 单个十六进制字符 → 数值（'F'→15） */
uint8_t func_hex_ch(char c);

/** 单个十进制字符 → 数值（'9'→9） */
uint8_t func_dec_ch(char c);

/** 十六进制字符串 "FF" → int 255 */
int     func_hex2dec(char *s);

/** 十进制字符串 "255" → int 255（支持负号） */
int     func_dec2dec(char *s);

/**
 * @brief 十六进制字符串 → 字节缓冲区
 * @param s   源字符串（如 "0102FF"）
 * @param dst 目标缓冲区
 * @param len [out]实际字节数
 * @return 0 成功，-1 奇数长度
 */
int     func_hex2buf(const char *s, char *dst, int *len);

/**
 * @brief int → 十进制字符串，右对齐前补零
 * @param width 最小宽度（不足补 0，如 width=4 val=255 → "0255"）
 */
char   *func_dec2str(char *buf, int sz, int val, int width);

/** int → 十六进制字符串（width=0 时不补零） */
char   *func_hex2str(char *buf, int sz, int val, int width);

/** float → 字符串 */
char   *func_float2str(char *buf, int sz, float f, int width);

/** 字节数组 → 十六进制字符串（如 {0x01,0xFF} → "01FF"） */
char   *func_buf2str(char *buf, int sz, const char *src, int n);

/** 字符串按空格分割为 argc/argv */
int     func_str2argv(char *s, uint8_t *argc, char *argv[], uint8_t max);

/* ================================================================
 * 时间处理函数
 * ================================================================ */

/** 系统时间 → "YYYY-MM-DD HH:MM:SS.mmm" 格式字符串 */
char *func_time_sys2str(char *buf, int sz, stru_time_sys *t);

/** 字符串 → 系统时间，解析失败返回 -1 */
int   func_str2time_sys(const char *s, stru_time_sys *t);

/** 获取当前时间（type: 1=stru_time_sys, 2=stru_time_cal） */
int   func_get_time(void *t, int type);

/** 设置系统时间（需要 root 权限） */
int   func_set_time(void *t, int type);

/** 系统时间 → 日历时间 */
void  func_time_sys2cal(stru_time_sys *src, stru_time_cal *dst);

/** 日历时间 → 系统时间 */
void  func_time_cal2sys(stru_time_cal *src, stru_time_sys *dst);

/* ================================================================
 * 文件目录操作函数
 * ================================================================ */

/** 判断目录是否存在（返回 1=存在, 0=不存在） */
int      func_dir_exist(const char *p);

/** 递归创建目录 */
int      func_make_dirs(const char *p);

/** 递归删除目录（含所有内容） */
int      func_del_dirs(const char *p);

/** 通过系统命令删除目录（rm -rf） */
int      func_del_dirs_cmd(const char *p);

/** 判断文件是否存在（返回 1=存在, 0=不存在） */
int      func_file_exist(const char *p);

/** 获取文件大小（字节），失败返回 0 */
uint32_t func_file_size(const char *p);

/** 读取文件到预分配缓冲区，out 返回实际读取字节数 */
int      func_read_file(const char *p, char *buf, uint32_t cap, uint32_t *out);

/** 读取文件到动态分配缓冲区（调用者负责 free） */
uint8_t *func_read_file_alloc(const char *p, uint32_t *out);

/** 写缓冲区到文件（覆盖模式） */
int      func_write_file(const char *p, const char *buf, uint32_t n);

/**
 * @brief 读取结构化的文件描述头
 * @param check 1=校验 flag 和 CRC，0=直接读取
 */
int      func_read_file_info(const char *p, stru_file_info *info, int check);

/* ================================================================
 * 进程管理函数（基于 /proc 文件系统）
 * ================================================================ */

/** 获取当前进程名称 */
int func_proc_self_name(char *buf, uint32_t sz);

/** 通过 PID 获取进程名称 */
int func_proc_name_by_pid(int pid, char *buf, uint32_t sz);

/** 获取当前进程 PID */
int func_proc_pid(void);

/** 通过进程名称获取 PID（返回 -1 表示未找到） */
int func_proc_pid_by_name(const char *name);

/** 通过 PID 判断进程是否存在 */
int func_proc_exist_by_pid(int pid);

/** 通过名称判断进程是否存在 */
int func_proc_exist_by_name(const char *name);

/** 通过 PID 获取进程可执行文件路径 */
int func_proc_path_by_pid(int pid, char *buf, uint32_t sz);

/** 获取当前进程可执行文件路径 */
int func_proc_self_path(char *buf, uint32_t sz);

/** 获取当前进程所在目录 */
int func_proc_self_dir(char *buf, uint32_t sz);

/* ================================================================
 * 环境变量路径函数
 * ================================================================ */

/** 获取工作目录路径（环境变量 WORK_PATH） */
int func_get_work_path(char *buf, uint32_t sz);

/** 获取系统配置路径（SYS_CFG_PATH） */
int func_get_syscfg_path(char *buf, uint32_t sz);

/** 获取应用根路径（APP_ROOT_PATH） */
int func_get_app_root(char *buf, uint32_t sz);

/** 获取历史数据根路径（HIS_ROOT_PATH） */
int func_get_his_root(char *buf, uint32_t sz);

/** 获取日志根路径（LOG_ROOT_PATH） */
int func_get_log_root(char *buf, uint32_t sz);

/** 获取数据库根路径（DBC_ROOT_PATH） */
int func_get_dbc_root(char *buf, uint32_t sz);

/** 获取脚本路径（SHELL_PATH） */
int func_get_shell_path(char *buf, uint32_t sz);

/** 获取更新包路径（UPDATE_PATH） */
int func_get_update_path(char *buf, uint32_t sz);

/** 拼接应用路径：APP_ROOT_PATH/app_name */
int func_get_app_path(const char *app, char *buf, uint32_t sz);

/** 拼接应用配置路径：APP_ROOT_PATH/app_name/ext */
int func_get_app_cfg(const char *app, const char *ext, char *buf, uint32_t sz);

/** 拼接应用历史路径：HIS_ROOT_PATH/app_name */
int func_get_app_his(const char *app, char *buf, uint32_t sz);

/** 拼接应用日志路径：LOG_ROOT_PATH/app_name */
int func_get_app_log(const char *app, char *buf, uint32_t sz);

/* ================================================================
 * IPC 消息队列函数（System V 消息队列）
 * ================================================================ */

/** 按进程名创建消息队列 */
int func_ipc_create_by_name(char *name, int *qid);

/** 按 PID 创建消息队列 */
int func_ipc_create_by_pid(int pid, int *qid);

/** 按进程名获取消息队列 ID（不存在则创建） */
int func_ipc_get_by_name(const char *name, int *qid);

/** 按 PID 获取消息队列 ID（不存在则创建） */
int func_ipc_get_by_pid(int pid, int *qid);

/** 发送原始字节到消息队列 */
int func_ipc_send_buf(int qid, uint8_t *tx, uint32_t n);

/** 从消息队列接收原始字节 */
int func_ipc_recv_buf(int qid, uint8_t *rx, uint32_t n);

/** 发送结构体消息 */
int func_ipc_send_msg(int qid, stru_ipc_msg *m);

/** 接收结构体消息 */
int func_ipc_recv_msg(int qid, stru_ipc_msg *m);

/** 删除消息队列 */
int func_ipc_delete(int qid);

#ifdef __cplusplus
}
#endif
#endif
