Files
scc/runtime/libcore/include/core_str.h
zzy 07f5d9331b feat(lexer, preprocessor): replace cstring conversion with copy and refactor macro expansion
- Replace `scc_cstring_from_cstr(scc_cstring_as_cstr(...))` with `scc_cstring_copy()` in lexer to fix memory leaks
- Extract macro expansion logic into separate `expand_macro.c` file
- Remove `expand_stack` parameter from `scc_pp_expand_macro()` function
- Add new parsing functions for macro replacement lists and arguments
- Add string utility functions for whitespace trimming and string joining
- Update memory stream documentation for clarity
2025-12-15 20:24:39 +08:00

202 lines
4.9 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 __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 初始化后的对象
*/
// FIXME need using `init` beacuse it not malloc
static inline scc_cstring_t scc_cstring_new(void) {
return (scc_cstring_t){.data = null, .size = 0, .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_new();
}
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__ */