mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-12-05 05:18:53 +08:00
447 lines
13 KiB
C
447 lines
13 KiB
C
#ifndef ACL_VSTRING_INCLUDE_H
|
||
#define ACL_VSTRING_INCLUDE_H
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#include "acl_define.h"
|
||
#include <stdarg.h>
|
||
#include "acl_vbuf.h"
|
||
#include "acl_dbuf_pool.h"
|
||
#include "acl_slice.h"
|
||
|
||
/**
|
||
* 封装了 ACL_VBUF,ACL_VSTRING 结构类型定义
|
||
*/
|
||
typedef struct ACL_VSTRING {
|
||
ACL_VBUF vbuf;
|
||
ssize_t maxlen;
|
||
ACL_SLICE_POOL *slice;
|
||
ACL_DBUF_POOL *dbuf;
|
||
ACL_FILE_HANDLE fd;
|
||
#if defined(_WIN32) || defined(_WIN64)
|
||
ACL_FILE_HANDLE hmap;
|
||
#endif
|
||
} ACL_VSTRING;
|
||
|
||
/**
|
||
* 初始化 ACL_VSTRING 结构并指定缺省的缓冲区大小,当用户在自己的函数或
|
||
* 内部以 ACL_VSTRING str 方式(非动态分配方式)使用时需要用此函数进行初始化,
|
||
* 另外,必须用 acl_vstring_free_buf 方式来释放由该函数分配的内部缓冲区
|
||
* @param vp {ACL_VSTRING*} 对象地址,不能为空
|
||
* @param len {size_t} 初始时缓冲区大小
|
||
*/
|
||
ACL_API void acl_vstring_init(ACL_VSTRING *vp, size_t len);
|
||
|
||
/**
|
||
* 当以 acl_vstring_init 初始化 ACL_VSTRING 对象时需要调用此函数释放缓冲区内存
|
||
* @param vp {ACL_VSTRING*} 对象地址,不能为空
|
||
*/
|
||
ACL_API void acl_vstring_free_buf(ACL_VSTRING *vp);
|
||
|
||
/**
|
||
* 动态分配一个 ACL_VSTRING 对象并指定内部缓冲区的初始化大小
|
||
* @param len {size_t} 初始时缓冲区大小
|
||
* @return {ACL_VSTRING*} 新分配的 ACL_VSTRING 对象
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_alloc(size_t len);
|
||
|
||
/**
|
||
* 动态分配一个 ACL_VSTRING 对象并指定内部缓冲区的初始化大小,
|
||
* 同时指定内存池对象,优化内存分配
|
||
* @param slice {ACL_SLICE_POOL*} 切片内存池管理对象
|
||
* @param len {size_t} 初始时缓冲区大小
|
||
* @return {ACL_VSTRING*} 新分配的 ACL_VSTRING 对象
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_slice_alloc(ACL_SLICE_POOL *slice, size_t len);
|
||
|
||
/**
|
||
* 动态分配一个 ACL_VSTRING 对象并指定内部缓冲区的初始化大小,
|
||
* 同时指定内存池对象,优化内存分配
|
||
* @param slice {ACL_SLICE_POOL*} 切片内存池管理对象
|
||
* @param len {size_t} 初始时缓冲区大小
|
||
* @return {ACL_VSTRING*} 新分配的 ACL_VSTRING 对象
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_dbuf_alloc(ACL_DBUF_POOL *dbuf, size_t len);
|
||
|
||
/**
|
||
* 采用内存映射文件方式分配内存时,调用此函数创建 ACL_VSTRING 动态缓冲区对象
|
||
* @param fd {ACL_FILE_HANDLE} 有效的文件句柄
|
||
* @param max_len {ssize_t} 所映射的最大内存大小
|
||
* @param init_len {ssize_t} 初始化时的内存映射大小
|
||
* @return {ACL_VSTRING*} 新创建的 ACL_VSTRING 对象
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_mmap_alloc(ACL_FILE_HANDLE fd,
|
||
ssize_t max_len, ssize_t init_len);
|
||
|
||
/**
|
||
* 设置 ACL_VSTRING 对象的属性, 目前该函数的功能还不够完善
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param ... 由 ACL_VSTRING_CTL_XXX 表示的控制参数,结束标志为
|
||
* ACL_VSTRING_CTL_END
|
||
*/
|
||
ACL_API void acl_vstring_ctl(ACL_VSTRING *vp,...);
|
||
|
||
#define ACL_VSTRING_CTL_MAXLEN 1
|
||
#define ACL_VSTRING_CTL_END 0
|
||
|
||
/**
|
||
* 将缓冲区内的数据截短至指定长度,同时保证缓冲区数据以 '\0' 结尾
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param len {size_t} 截短后的长度
|
||
* @return {ACL_VSTRING*} 与 vp 相同
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_truncate(ACL_VSTRING *vp, size_t len);
|
||
|
||
/**
|
||
* 释放由 acl_vstring_alloc 动态分配的 ACL_VSTRING 对象
|
||
* @param vp {ACL_VSTRING*}
|
||
*/
|
||
ACL_API void acl_vstring_free(ACL_VSTRING *vp);
|
||
|
||
/**
|
||
* 拷贝字符串
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param src {const char*} 源字符串
|
||
* @return {ACL_VSTRING*} 与 vp 相同
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_strcpy(ACL_VSTRING *vp, const char *src);
|
||
|
||
/**
|
||
* 拷贝字符串,但不得超过规定长度限制
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param src {const char*} 源字符串
|
||
* @param len {size_t} 规定长度限制
|
||
* @return {ACL_VSTRING*} 与 vp 相同
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_strncpy(ACL_VSTRING *vp,
|
||
const char *src, size_t len);
|
||
|
||
/**
|
||
* 附加拷贝字符串
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param src {const char*} 源字符串
|
||
* @return {ACL_VSTRING*} 与 vp 相同
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_strcat(ACL_VSTRING *vp, const char *src);
|
||
|
||
/**
|
||
* 附加拷贝字符串,但不得超过规定长度限制
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param src {const char*} 源字符串
|
||
* @param len {size_t} 规定长度限制
|
||
* @return {ACL_VSTRING*} 与 vp 相同
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_strncat(ACL_VSTRING *vp,
|
||
const char *src, size_t len);
|
||
|
||
/**
|
||
* 拷贝内存区数据,同时保证目标缓冲区尾部置 '\0'
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param src {const char*} 源数据地址
|
||
* @param len {size_t} 源数据长度
|
||
* @return {ACL_VSTRING*} 与 vp 相同
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_memcpy(ACL_VSTRING *vp,
|
||
const char *src, size_t len);
|
||
|
||
/**
|
||
* 移动内存区数据, 源数据与目标地址的内存区可以是同一块内存区也可以不是
|
||
* 同一块内存区,该函数保证目标地址尾部以 '\0' 结尾
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param src {const char*} 源数据地址
|
||
* @param len {size_t} 源数据长度
|
||
* @return {ACL_VSTRING*} 与 vp 相同
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_memmove(ACL_VSTRING *vp,
|
||
const char *src, size_t len);
|
||
|
||
/**
|
||
* 拷贝内存区,该函数保证目标缓冲区以 '\0' 结尾
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param src {const char*} 源数据地址
|
||
* @param len {size_t} 源数据长度
|
||
* @return {ACL_VSTRING*} 与 vp 相同
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_memcat(ACL_VSTRING *vp,
|
||
const char *src, size_t len);
|
||
|
||
/**
|
||
* 查找某个字符
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param ch {int} 要查找的字符
|
||
* @return {char*} 目标字符所在位置的地址, 如果未查到则返回 NULL,
|
||
* 注:该返回地址是不能被单独释放的,因为其由 ACL_VSTRING 对象统一进行管理
|
||
*/
|
||
ACL_API char *acl_vstring_memchr(ACL_VSTRING *vp, int ch);
|
||
|
||
/**
|
||
* 查找某个字符串,字符串大小写敏感
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param needle {const char*} 要查找的字符
|
||
* @return {char*} 目标字符所在位置的地址, 如果未查到则返回 NULL,
|
||
* 注:该返回地址是不能被单独释放的,因为其由 ACL_VSTRING 对象统一进行管理
|
||
*/
|
||
ACL_API char *acl_vstring_strstr(ACL_VSTRING *vp, const char *needle);
|
||
|
||
/**
|
||
* 查找某个字符串,忽略字符串大小写
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param needle {const char*} 要查找的字符
|
||
* @return {char*} 目标字符所在位置的地址, 如果未查到则返回 NULL,
|
||
* 注:该返回地址是不能被单独释放的,因为其由 ACL_VSTRING 对象统一进行管理
|
||
*/
|
||
ACL_API char *acl_vstring_strcasestr(ACL_VSTRING *vp, const char *needle);
|
||
|
||
/**
|
||
* 从后向前查找字符串,字符串大小写敏感
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param needle {const char*} 要查找的字符
|
||
* @return {char*} 目标字符所在位置的地址, 如果未查到则返回 NULL,
|
||
* 注:该返回地址是不能被单独释放的,因为其由 ACL_VSTRING 对象统一进行管理
|
||
*/
|
||
ACL_API char *acl_vstring_rstrstr(ACL_VSTRING *vp, const char *needle);
|
||
|
||
/**
|
||
* 从后向前查找字符串,字符串大小写不敏感
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param needle {const char*} 要查找的字符
|
||
* @return {char*} 目标字符所在位置的地址, 如果未查到则返回 NULL,
|
||
* 注:该返回地址是不能被单独释放的,因为其由 ACL_VSTRING 对象统一进行管理
|
||
*/
|
||
ACL_API char *acl_vstring_rstrcasestr(ACL_VSTRING *vp, const char *needle);
|
||
|
||
/**
|
||
* 向缓冲区的某个指定位置后添加数据,同时保证目标缓冲区数据以 '\0' 结尾
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param start {size_t} 指定的位置
|
||
* @param buf {const char*} 数据地址
|
||
* @param len {size_t} 数据长度
|
||
* @return {ACL_VSTRING*} 与 vp 相同
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_insert(ACL_VSTRING *vp, size_t start,
|
||
const char *buf, size_t len);
|
||
|
||
/**
|
||
* 向缓冲区的头部添加数据,同时保证目标缓冲区数据以 '\0' 结尾
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param buf {const char*} 数据地址
|
||
* @param len {size_t} 数据长度
|
||
* @return {ACL_VSTRING*} 与 vp 相同
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_prepend(ACL_VSTRING *vp,
|
||
const char *buf, size_t len);
|
||
|
||
/**
|
||
* 向缓冲区按格式方式添加数据
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param format {const char*} 格式化字符串
|
||
* @param ... 变参序列
|
||
* @return {ACL_VSTRING*} 与 vp 相同
|
||
*/
|
||
ACL_API ACL_VSTRING *ACL_PRINTF(2, 3) acl_vstring_sprintf(ACL_VSTRING *vp,
|
||
const char *format,...);
|
||
|
||
/**
|
||
* 以附加方式向缓冲区按格式方式添加数据
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param format {const char*} 格式化字符串
|
||
* @param ... 变参序列
|
||
* @return {ACL_VSTRING*} 与 vp 相同
|
||
*/
|
||
ACL_API ACL_VSTRING *ACL_PRINTF(2, 3) acl_vstring_sprintf_append(
|
||
ACL_VSTRING *vp, const char *format,...);
|
||
|
||
/**
|
||
* 导出缓冲区内的数据区同时将 ACL_VSTRING 对象释放,用户需要单独调用
|
||
* acl_myfree 来释放返回的数据区内存
|
||
* @param vp {ACL_VSTRING*}
|
||
* @return {char*} 数据区地址,当返回值不为 NULL 时用户需要单独调用
|
||
* acl_myfree 来释放该地址,否则会造成内存泄漏
|
||
*/
|
||
ACL_API char *acl_vstring_export(ACL_VSTRING *vp);
|
||
|
||
/**
|
||
* 将用户的存储字符串的动态分配内存区导入并生成新的 ACL_VSTRING 对象
|
||
* @param str {char*} 外部动态分配的存储字符串的内存地址
|
||
* @return {ACL_VSTRING*} 新分配的 ACL_VSTRING 对象
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_import(char *str);
|
||
|
||
/**
|
||
* 将动态内存区与 ACL_VSTRING 粘合
|
||
* 注:vp 不能是调用 acl_vstring_alloc 产生的,并且不能调用 acl_vstring_init
|
||
* 进行过初始化, vp 可以是由 acl_mymalloc 产生或位于栈上的一个变量
|
||
* (如: ACL_VSTRING v)
|
||
* @param vp {ACL_VSTRING*} 需由 acl_mymalloc 生成或是一个栈变量, 当以
|
||
* acl_mymalloc 方式生成的时应该通过 acl_myfree 释放它
|
||
* @param buf {void*} 用户传递的内存区, 可以是栈变量
|
||
* @param len {size_t} buf 内存区的长度
|
||
*/
|
||
ACL_API void acl_vstring_glue(ACL_VSTRING *vp, void *buf, size_t len);
|
||
|
||
/**
|
||
* 取得某个位置的字符
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param len {size_t} 位置,如果该值越界,则函数内部会 fatal
|
||
* @return {char} 查找的字符
|
||
*/
|
||
ACL_API char acl_vstring_charat(ACL_VSTRING *vp, size_t len);
|
||
|
||
/**
|
||
* 按规定格式添加数据
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param format {const char*}
|
||
* @param ap {va_list}
|
||
* @return {ACL_VSTRING*} 与 vp 相同
|
||
* @see acl_vstring_sprintf
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_vsprintf(ACL_VSTRING *vp,
|
||
const char *format, va_list ap);
|
||
|
||
/**
|
||
* 按规定格式向尾部添加数据
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param format {const char*}
|
||
* @param ap {va_list}
|
||
* @return {ACL_VSTRING*} 与 vp 相同
|
||
*/
|
||
ACL_API ACL_VSTRING *acl_vstring_vsprintf_append(ACL_VSTRING *vp,
|
||
const char *format, va_list ap);
|
||
|
||
/**
|
||
* 按规定格式向头部添加数据
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param format {const char*}
|
||
* @param ... 变参序列
|
||
* @return {ACL_VSTRING*} 与 vp 相同
|
||
*/
|
||
ACL_API ACL_VSTRING *ACL_PRINTF(2, 3) acl_vstring_sprintf_prepend(
|
||
ACL_VSTRING *vp, const char *format, ...);
|
||
|
||
/**
|
||
* 从源串中获得一行数据(不含 "\r\n" 和 "\n"),同时将剩余数据缓存起来, 如果
|
||
* 未获得完整行,则只缓存源串
|
||
* @param vp {ACL_VSTRING*} 字符串数据缓存区
|
||
* @param src {const char**} 源字符串指针地址, 返回后指针地址移动至下一位置
|
||
* @param dlen {size_t} 源字符串数据长度
|
||
* @return {const ACL_VSTRING*} NULL, 表示未找到 "\r\n" 或 "\n",但会将剩余
|
||
* 的数据拷贝至缓冲区内,应用需要通过 ACL_VSTRING_LEN 判断缓冲区中是否还有
|
||
* 数据;!NULL,表示读到完整行
|
||
* 注:读到完整行后应该调用 ACL_VSTRING_RESET(vp) 将缓冲区清空
|
||
*/
|
||
ACL_API const ACL_VSTRING *acl_buffer_gets_nonl(ACL_VSTRING *vp,
|
||
const char **src, size_t dlen);
|
||
|
||
/**
|
||
* 从源串中获得一行数据(包含 "\r\n" 或 "\n"),同时将剩余数据缓存起来,
|
||
* 如果未获得完整行,则只缓存源串
|
||
* @param vp {ACL_VSTRING*} 字符串数据缓存区
|
||
* @param src {const char**} 源字符串指针地址, 返回后指针地址移动至下一位置
|
||
* @param dlen {size_t} 源字符串数据长度
|
||
* @return {const ACL_VSTRING*} NULL, 表示未找到 "\r\n" 或 "\n",但会将剩余
|
||
* 的数据拷贝至缓冲区内,应用需要通过 ACL_VSTRING_LEN 判断缓冲区中是否还有
|
||
* 数据;!NULL,表示读到完整行
|
||
* 注:读到完整行后应该调用 ACL_VSTRING_RESET(vp) 将缓冲区清空
|
||
*/
|
||
ACL_API const ACL_VSTRING *acl_buffer_gets(ACL_VSTRING *vp,
|
||
const char **src, size_t dlen);
|
||
|
||
/*
|
||
* Macros. Unsafe macros have UPPERCASE names.
|
||
*/
|
||
#define ACL_VSTRING_SPACE(vp, len) ((vp)->vbuf.space(&(vp)->vbuf, len))
|
||
|
||
/**
|
||
* 取得当前 ACL_VSTRING 数据存储地址
|
||
* @param vp {ACL_VSTRING*}
|
||
* @return {char*}
|
||
*/
|
||
#define acl_vstring_str(vp) ((char *) (vp)->vbuf.data)
|
||
|
||
/**
|
||
* 取得当前 ACL_VSTRING 所存储的数据的长度
|
||
* @param vp {ACL_VSTRING*}
|
||
* @return {int}
|
||
*/
|
||
#define ACL_VSTRING_LEN(vp) (size_t) ((vp)->vbuf.ptr - (vp)->vbuf.data)
|
||
|
||
/**
|
||
* 取得当前 ACL_VSTRING 内部缓冲区的总大小
|
||
* @param vp {ACL_VSTRING*}
|
||
* @return {int}
|
||
*/
|
||
#define ACL_VSTRING_SIZE(vp) ((vp)->vbuf.len)
|
||
|
||
/**
|
||
* 取得当前 ACL_VSTRING 的数据偏移指针位置
|
||
* @param vp {ACL_VSTRING*}
|
||
* @return {char*}
|
||
*/
|
||
#define acl_vstring_end(vp) ((char *) (vp)->vbuf.ptr)
|
||
|
||
/**
|
||
* 将 ACL_VSTRING 的数据偏移指针位置置 0
|
||
* @param vp {ACL_VSTRING*}
|
||
*/
|
||
#define ACL_VSTRING_TERMINATE(vp) { \
|
||
if ((vp)->vbuf.cnt <= 0) \
|
||
ACL_VSTRING_SPACE((vp), 1); \
|
||
if ((vp)->vbuf.cnt > 0) \
|
||
*(vp)->vbuf.ptr = 0; \
|
||
else if ((vp)->vbuf.ptr > (vp)->vbuf.data) { \
|
||
(vp)->vbuf.ptr--; \
|
||
*(vp)->vbuf.ptr = 0; \
|
||
(vp)->vbuf.cnt++; \
|
||
} \
|
||
}
|
||
|
||
/**
|
||
* 重置 ACL_VSTRING 内部缓冲区指针地址起始位置,但不会将尾部数据置 0,应用可以
|
||
* 通过调用 ACL_VSTRING_TERMINATE 将缓冲数据尾部置 0
|
||
* @param vp {ACL_VSTRING*}
|
||
*/
|
||
#define ACL_VSTRING_RESET(vp) { \
|
||
(vp)->vbuf.ptr = (vp)->vbuf.data; \
|
||
(vp)->vbuf.cnt = (vp)->vbuf.len; \
|
||
acl_vbuf_clearerr(&(vp)->vbuf); \
|
||
}
|
||
|
||
/**
|
||
* 添加一个字符至 ACL_VSTRING 缓冲区
|
||
* @param vp {ACL_VSTRING*}
|
||
* @param ch {int} 字符
|
||
*/
|
||
#define ACL_VSTRING_ADDCH(vp, ch) ACL_VBUF_PUT(&(vp)->vbuf, ch)
|
||
|
||
/**
|
||
* 移动数据偏移指针至内部缓冲区尾部
|
||
* @param vp {ACL_VSTRING*}
|
||
*/
|
||
#define ACL_VSTRING_SKIP(vp) { \
|
||
while ((vp)->vbuf.cnt > 0 && *(vp)->vbuf.ptr) \
|
||
(vp)->vbuf.ptr++, (vp)->vbuf.cnt--; \
|
||
}
|
||
|
||
/**
|
||
* 当前 ACL_VSTRING 中还有多少数据可用
|
||
* @param vp {ACL_VSTRING*}
|
||
*/
|
||
#define acl_vstring_avail(vp) ((vp)->vbuf.cnt)
|
||
|
||
/**
|
||
* The following macro is not part of the public interface, because it can
|
||
* really screw up a buffer by positioning past allocated memory.
|
||
*/
|
||
#define ACL_VSTRING_AT_OFFSET(vp, offset) { \
|
||
(vp)->vbuf.ptr = (vp)->vbuf.data + (offset); \
|
||
(vp)->vbuf.cnt = (vp)->vbuf.len - (offset); \
|
||
}
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif
|