- Replace `scc_probe_stream_consume` with `scc_probe_stream_next` for consistent stream advancement - Remove redundant `scc_probe_stream_reset` calls before peeking, as `next` and `peek` handle state - Update `scc_cstring_new` to `scc_cstring_create` and `scc_pos_init` to `scc_pos_create` for naming consistency - Change `scc_pp_macro_get` parameter to `const scc_cstring_t*` for better const-correctness - Improves code clarity and maintains proper stream position tracking
208 lines
5.0 KiB
C
208 lines
5.0 KiB
C
#ifndef __SCC_CORE_STR_H__
|
||
#define __SCC_CORE_STR_H__
|
||
|
||
#include "core_impl.h"
|
||
#include "core_log.h"
|
||
#include "core_type.h"
|
||
|
||
/**
|
||
* @brief 动态字符串结构体
|
||
* @attention 创建的字符串对象需要使用 scc_cstring_free 释放
|
||
*/
|
||
typedef struct scc_cstring {
|
||
usize size; /**< 字符串当前大小(包括结尾的'\0')*/
|
||
usize cap; /**< 分配的容量 */
|
||
char *data; /**< 实际存储数据的指针 */
|
||
} scc_cstring_t;
|
||
|
||
/**
|
||
* @brief 创建一个新的空动态字符串对象
|
||
*
|
||
* @return cstring_t 初始化后的对象
|
||
*/
|
||
static inline scc_cstring_t scc_cstring_create(void) {
|
||
return (scc_cstring_t){.data = null, .size = 0, .cap = 0};
|
||
}
|
||
|
||
static inline void scc_cstring_init(scc_cstring_t *string) {
|
||
Assert(string != null);
|
||
string->data = null;
|
||
string->size = 0;
|
||
string->cap = 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 从 C 风格字符串创建一个动态字符串副本
|
||
*
|
||
* @param s 输入的 C 风格字符串
|
||
* @return cstring_t 新建对象,包含输入字符串的副本
|
||
*/
|
||
static inline scc_cstring_t scc_cstring_from_cstr(const char *s) {
|
||
if (s == null) {
|
||
return scc_cstring_create();
|
||
}
|
||
|
||
usize len = 0;
|
||
const char *p = s;
|
||
while (*p++)
|
||
len++;
|
||
|
||
char *data = (char *)scc_malloc(len + 1);
|
||
Assert(data != null);
|
||
scc_memcpy(data, s, len);
|
||
data[len] = '\0';
|
||
|
||
return (scc_cstring_t){.size = len + 1, .cap = len + 1, .data = data};
|
||
}
|
||
|
||
static inline scc_cstring_t scc_cstring_copy(const scc_cstring_t *s) {
|
||
return scc_cstring_from_cstr(s->data);
|
||
}
|
||
|
||
/**
|
||
* @brief 释放动态字符串占用的内存资源
|
||
*
|
||
* @param str 要被释放的字符串指针
|
||
*/
|
||
static inline void scc_cstring_free(scc_cstring_t *str) {
|
||
if (str == null) {
|
||
return;
|
||
}
|
||
if (str->cap != 0 && str->data != null) {
|
||
scc_free(str->data);
|
||
str->data = null;
|
||
}
|
||
str->size = 0;
|
||
str->cap = 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 向动态字符串末尾追加一段 C 风格字符串
|
||
*
|
||
* @param str 目标动态字符串指针
|
||
* @param data 要追加的 C 字符串指针
|
||
* @param len 要追加的 C 字符串长度
|
||
*/
|
||
static inline void scc_cstring_append_cstr(scc_cstring_t *str, const char *data,
|
||
usize len) {
|
||
if (str == null || data == null || len == 0) {
|
||
return;
|
||
}
|
||
|
||
if (str->cap == 0) {
|
||
// add '\0' to str
|
||
str->size = 1;
|
||
}
|
||
|
||
// 如果需要扩容
|
||
if (str->size + len > str->cap) {
|
||
usize new_cap = str->cap;
|
||
while (new_cap < str->size + len) {
|
||
if (new_cap == 0) {
|
||
new_cap = str->size + len;
|
||
break;
|
||
} else {
|
||
new_cap *= 2;
|
||
}
|
||
// FIXME 处理溢出情况
|
||
}
|
||
|
||
char *new_data = (char *)scc_realloc(str->data, new_cap);
|
||
Assert(new_data != null);
|
||
|
||
str->data = new_data;
|
||
str->cap = new_cap;
|
||
}
|
||
|
||
scc_memcpy(str->data + str->size - 1, data, len);
|
||
str->size += len;
|
||
str->data[str->size - 1] = '\0'; // 保证 C 字符串兼容性
|
||
}
|
||
|
||
/**
|
||
* @brief 向动态字符串末尾追加另一个动态字符串
|
||
*
|
||
* @param str 目标动态字符串指针
|
||
* @param other 要追加的动态字符串指针
|
||
*/
|
||
static inline void scc_cstring_append(scc_cstring_t *str,
|
||
const scc_cstring_t *other) {
|
||
scc_cstring_append_cstr(str, other->data, other->size - 1);
|
||
}
|
||
|
||
/**
|
||
* @brief 向动态字符串末尾追加一个字符
|
||
*
|
||
* @param str 目标动态字符串指针
|
||
* @param ch 要追加的字符
|
||
*/
|
||
static inline void scc_cstring_append_ch(scc_cstring_t *str, char ch) {
|
||
scc_cstring_append_cstr(str, &ch, 1);
|
||
}
|
||
|
||
/**
|
||
* @brief 获取动态字符串的实际内容长度 不包括结尾的'\0'
|
||
*
|
||
* @param str 动态字符串指针
|
||
* @return usize 字符串实际长度
|
||
*/
|
||
static inline usize scc_cstring_len(const scc_cstring_t *str) {
|
||
if (str == null) {
|
||
return 0;
|
||
}
|
||
if (str->size == 0) {
|
||
return 0;
|
||
}
|
||
return str->size - 1;
|
||
}
|
||
|
||
/**
|
||
* @brief 判断动态字符串是否为空
|
||
*
|
||
* @param str 动态字符串指针
|
||
* @return cbool
|
||
*/
|
||
static inline cbool scc_cstring_is_empty(const scc_cstring_t *str) {
|
||
return str == null || str->size == 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 清空动态字符串内容但保留已分配的内存空间
|
||
*
|
||
* @param str 动态字符串指针
|
||
*/
|
||
static inline void scc_cstring_clear(scc_cstring_t *str) {
|
||
if (str) {
|
||
str->size = 1;
|
||
if (str->data) {
|
||
str->data[0] = '\0';
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 将动态字符串转换为 C 风格字符串
|
||
*
|
||
* @param str 动态字符串指针
|
||
* @return char* 返回指向内部缓冲区的 C 风格字符串指针
|
||
*/
|
||
static inline char *scc_cstring_as_cstr(const scc_cstring_t *str) {
|
||
if (str == null || str->data == null) {
|
||
return "";
|
||
}
|
||
return str->data;
|
||
}
|
||
|
||
static inline char *scc_cstring_move_cstr(scc_cstring_t *str) {
|
||
if (str == null || str->data == null) {
|
||
return "";
|
||
}
|
||
char *ret = str->data;
|
||
str->data = null;
|
||
str->cap = 0;
|
||
str->size = 0;
|
||
return ret;
|
||
}
|
||
|
||
#endif /* __SCC_CORE_STR_H__ */
|