acl/lib_acl/include/stdlib/acl_vstring.h

443 lines
13 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 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_VBUFACL_VSTRING 结构类型定义
*/
typedef struct ACL_VSTRING {
ACL_VBUF vbuf;
ACL_SLICE_POOL *slice;
ACL_DBUF_POOL *dbuf;
ssize_t maxlen;
} 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