stage1 重构代码
This commit is contained in:
61
stage0/include/color.h
Normal file
61
stage0/include/color.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @file color.h
|
||||
* @brief ANSI终端颜色控制码定义
|
||||
*
|
||||
* 提供跨平台的终端文本颜色和样式控制支持
|
||||
*/
|
||||
|
||||
#ifndef __SCC_TERMINAL_COLOR_H__
|
||||
#define __SCC_TERMINAL_COLOR_H__
|
||||
|
||||
/* clang-format off */
|
||||
/// @name 前景色控制码
|
||||
/// @{
|
||||
#define ANSI_FG_BLACK "\33[30m" ///< 黑色前景
|
||||
#define ANSI_FG_RED "\33[31m" ///< 红色前景
|
||||
#define ANSI_FG_GREEN "\33[32m" ///< 绿色前景
|
||||
#define ANSI_FG_YELLOW "\33[33m" ///< 黄色前景
|
||||
#define ANSI_FG_BLUE "\33[34m" ///< 蓝色前景
|
||||
#define ANSI_FG_MAGENTA "\33[35m" ///< 品红色前景
|
||||
#define ANSI_FG_CYAN "\33[36m" ///< 青色前景
|
||||
#define ANSI_FG_WHITE "\33[37m" ///< 白色前景
|
||||
/// @}
|
||||
|
||||
/// @name 背景色控制码
|
||||
/// @{
|
||||
#define ANSI_BG_BLACK "\33[40m" ///< 黑色背景
|
||||
#define ANSI_BG_RED "\33[41m" ///< 红色背景
|
||||
#define ANSI_BG_GREEN "\33[42m" ///< 绿色背景
|
||||
#define ANSI_BG_YELLOW "\33[43m" ///< 黄色背景
|
||||
#define ANSI_BG_BLUE "\33[44m" ///< 蓝色背景
|
||||
#define ANSI_BG_MAGENTA "\33[45m" ///< 品红色背景(注:原始代码此处应为45m)
|
||||
#define ANSI_BG_CYAN "\33[46m" ///< 青色背景
|
||||
#define ANSI_BG_WHITE "\33[47m" ///< 白色背景
|
||||
/// @}
|
||||
|
||||
/// @name 文字样式控制码
|
||||
/// @{
|
||||
#define ANSI_UNDERLINED "\33[4m" ///< 下划线样式
|
||||
#define ANSI_BOLD "\33[1m" ///< 粗体样式
|
||||
#define ANSI_NONE "\33[0m" ///< 重置所有样式
|
||||
/// @}
|
||||
/* clang-format on */
|
||||
|
||||
/**
|
||||
* @def ANSI_FMT
|
||||
* @brief 安全文本格式化宏
|
||||
* @param str 目标字符串
|
||||
* @param fmt ANSI格式序列(可组合多个样式)
|
||||
*
|
||||
* @note 当定义ANSI_FMT_DISABLE时自动禁用颜色输出
|
||||
* @code
|
||||
* printf(ANSI_FMT("Warning!", ANSI_FG_YELLOW ANSI_BOLD));
|
||||
* @endcode
|
||||
*/
|
||||
#ifndef ANSI_FMT_DISABLE
|
||||
#define ANSI_FMT(str, fmt) fmt str ANSI_NONE ///< 启用样式包裹
|
||||
#else
|
||||
#define ANSI_FMT(str, fmt) str ///< 禁用样式输出
|
||||
#endif
|
||||
|
||||
#endif /* __SCC_TERMINAL_COLOR_H__ */
|
||||
@@ -9,7 +9,8 @@
|
||||
#ifndef nullptr
|
||||
#define nullptr NULL
|
||||
#endif
|
||||
typedef size_t usize;
|
||||
typedef uintptr_t usize;
|
||||
typedef intptr_t isize;
|
||||
|
||||
#define MAP_TYPEOF __typeof__
|
||||
|
||||
@@ -26,150 +27,147 @@ typedef size_t usize;
|
||||
#define MAP_CMP_INT(a, b) ((a) != (b))
|
||||
|
||||
static inline usize map_hash_str(const char *s) {
|
||||
usize h = 5381;
|
||||
while (*s)
|
||||
h = ((h << 5) + h) + (unsigned char)*s++;
|
||||
return h;
|
||||
usize h = 5381;
|
||||
while (*s)
|
||||
h = ((h << 5) + h) + (unsigned char)*s++;
|
||||
return h;
|
||||
}
|
||||
#define MAP_HASH_STR map_hash_str
|
||||
#define MAP_CMP_STR strcmp
|
||||
|
||||
/* ---------- 数据结构宏 ---------- */
|
||||
#define MAP_SLOT(key_t, val_t) \
|
||||
struct { \
|
||||
key_t key; \
|
||||
val_t val; \
|
||||
char state; \
|
||||
}
|
||||
#define MAP_SLOT(key_t, val_t) \
|
||||
struct { \
|
||||
key_t key; \
|
||||
val_t val; \
|
||||
char state; \
|
||||
}
|
||||
|
||||
#define MAP(key_t, val_t) \
|
||||
struct { \
|
||||
usize size; \
|
||||
usize cap; \
|
||||
MAP_SLOT(key_t, val_t) * data; \
|
||||
usize (*hash)(key_t); \
|
||||
int (*cmp)(key_t, key_t); \
|
||||
}
|
||||
#define MAP(key_t, val_t) \
|
||||
struct { \
|
||||
usize size; \
|
||||
usize cap; \
|
||||
MAP_SLOT(key_t, val_t) * data; \
|
||||
usize (*hash)(key_t); \
|
||||
int (*cmp)(key_t, key_t); \
|
||||
}
|
||||
|
||||
/* ---------- 操作宏 ---------- */
|
||||
|
||||
/** 初始化,必须提供哈希和比较函数 */
|
||||
#define map_init(map, hash_fn, cmp_fn) \
|
||||
do { \
|
||||
(map).size = 0; \
|
||||
(map).cap = 0; \
|
||||
(map).data = nullptr; \
|
||||
(map).hash = (hash_fn); \
|
||||
(map).cmp = (cmp_fn); \
|
||||
} while (0)
|
||||
#define map_init(map, hash_fn, cmp_fn) \
|
||||
do { \
|
||||
(map).size = 0; \
|
||||
(map).cap = 0; \
|
||||
(map).data = nullptr; \
|
||||
(map).hash = (hash_fn); \
|
||||
(map).cmp = (cmp_fn); \
|
||||
} while (0)
|
||||
|
||||
/** 释放内部数组 */
|
||||
#define map_free(map) \
|
||||
do { \
|
||||
free((map).data); \
|
||||
(map).data = nullptr; \
|
||||
(map).size = (map).cap = 0; \
|
||||
} while (0)
|
||||
#define map_free(map) \
|
||||
do { \
|
||||
free((map).data); \
|
||||
(map).data = nullptr; \
|
||||
(map).size = (map).cap = 0; \
|
||||
} while (0)
|
||||
|
||||
/** 遍历所有有效元素 */
|
||||
#define map_for(map, idx) \
|
||||
for (usize(idx) = 0; (idx) < (map).cap; ++(idx)) \
|
||||
if ((map).data[(idx)].state == __MAP_SLOT_OCCUPIED)
|
||||
#define map_for(map, idx) \
|
||||
for (usize(idx) = 0; (idx) < (map).cap; ++(idx)) \
|
||||
if ((map).data[(idx)].state == __MAP_SLOT_OCCUPIED)
|
||||
|
||||
/**
|
||||
* 插入(若键已存在则更新值)
|
||||
* 注意:扩容使用 realloc,失败会 abort(可自行修改错误处理)
|
||||
*/
|
||||
#define map_put(map, _key, _val) \
|
||||
do { \
|
||||
/* 扩容 */ \
|
||||
if ((map).cap == 0 || \
|
||||
(map).size * 128 / (map).cap >= MAP_DEFAULT_LOAD_FACTOR) { \
|
||||
usize new_cap = (map).cap == 0 ? 8 : (map).cap * 2; \
|
||||
MAP_SLOT(MAP_TYPEOF((map).data->key), \
|
||||
MAP_TYPEOF((map).data->val)) *new_data = \
|
||||
calloc(new_cap, sizeof(*new_data)); \
|
||||
if (!new_data) \
|
||||
abort(); \
|
||||
/* 重新插入旧元素 */ \
|
||||
for (usize _i = 0; _i < (map).cap; ++_i) { \
|
||||
if ((map).data[_i].state == __MAP_SLOT_OCCUPIED) { \
|
||||
usize _h = (map).hash((map).data[_i].key) & (new_cap - 1); \
|
||||
while (new_data[_h].state == __MAP_SLOT_OCCUPIED) \
|
||||
_h = (_h + 1) & (new_cap - 1); \
|
||||
new_data[_h].key = (map).data[_i].key; \
|
||||
new_data[_h].val = (map).data[_i].val; \
|
||||
new_data[_h].state = __MAP_SLOT_OCCUPIED; \
|
||||
} \
|
||||
} \
|
||||
free((map).data); \
|
||||
(map).data = (void *)new_data; \
|
||||
(map).cap = new_cap; \
|
||||
} \
|
||||
/* 查找或插入 */ \
|
||||
usize _mask = (map).cap - 1; \
|
||||
usize _idx = (map).hash(_key) & _mask; \
|
||||
usize _first_del = (usize) - 1; \
|
||||
while ((map).data[_idx].state != __MAP_SLOT_EMPTY) { \
|
||||
if ((map).data[_idx].state == __MAP_SLOT_OCCUPIED && \
|
||||
(map).cmp((map).data[_idx].key, _key) == 0) { \
|
||||
(map).data[_idx].val = _val; \
|
||||
break; \
|
||||
} \
|
||||
if ((map).data[_idx].state == __MAP_SLOT_DELETED && \
|
||||
_first_del == (usize) - 1) \
|
||||
_first_del = _idx; \
|
||||
_idx = (_idx + 1) & _mask; \
|
||||
} \
|
||||
if ((map).data[_idx].state == __MAP_SLOT_EMPTY) { \
|
||||
usize _target = (_first_del != (usize) - 1) ? _first_del : _idx; \
|
||||
(map).data[_target].key = _key; \
|
||||
(map).data[_target].val = _val; \
|
||||
(map).data[_target].state = __MAP_SLOT_OCCUPIED; \
|
||||
++(map).size; \
|
||||
} \
|
||||
} while (0)
|
||||
#define map_put(map, _key, _val) \
|
||||
do { \
|
||||
/* 扩容 */ \
|
||||
if ((map).cap == 0 || (map).size * 128 / (map).cap >= MAP_DEFAULT_LOAD_FACTOR) { \
|
||||
usize new_cap = (map).cap == 0 ? 8 : (map).cap * 2; \
|
||||
MAP_SLOT(MAP_TYPEOF((map).data->key), MAP_TYPEOF((map).data->val)) *new_data = \
|
||||
calloc(new_cap, sizeof(*new_data)); \
|
||||
if (!new_data) \
|
||||
abort(); \
|
||||
/* 重新插入旧元素 */ \
|
||||
for (usize _i = 0; _i < (map).cap; ++_i) { \
|
||||
if ((map).data[_i].state == __MAP_SLOT_OCCUPIED) { \
|
||||
usize _h = (map).hash((map).data[_i].key) & (new_cap - 1); \
|
||||
while (new_data[_h].state == __MAP_SLOT_OCCUPIED) \
|
||||
_h = (_h + 1) & (new_cap - 1); \
|
||||
new_data[_h].key = (map).data[_i].key; \
|
||||
new_data[_h].val = (map).data[_i].val; \
|
||||
new_data[_h].state = __MAP_SLOT_OCCUPIED; \
|
||||
} \
|
||||
} \
|
||||
free((map).data); \
|
||||
(map).data = (void *)new_data; \
|
||||
(map).cap = new_cap; \
|
||||
} \
|
||||
/* 查找或插入 */ \
|
||||
usize _mask = (map).cap - 1; \
|
||||
usize _idx = (map).hash(_key) & _mask; \
|
||||
usize _first_del = (usize) - 1; \
|
||||
while ((map).data[_idx].state != __MAP_SLOT_EMPTY) { \
|
||||
if ((map).data[_idx].state == __MAP_SLOT_OCCUPIED && \
|
||||
(map).cmp((map).data[_idx].key, _key) == 0) { \
|
||||
(map).data[_idx].val = _val; \
|
||||
break; \
|
||||
} \
|
||||
if ((map).data[_idx].state == __MAP_SLOT_DELETED && _first_del == (usize) - 1) \
|
||||
_first_del = _idx; \
|
||||
_idx = (_idx + 1) & _mask; \
|
||||
} \
|
||||
if ((map).data[_idx].state == __MAP_SLOT_EMPTY) { \
|
||||
usize _target = (_first_del != (usize) - 1) ? _first_del : _idx; \
|
||||
(map).data[_target].key = _key; \
|
||||
(map).data[_target].val = _val; \
|
||||
(map).data[_target].state = __MAP_SLOT_OCCUPIED; \
|
||||
++(map).size; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* 查询:若找到,*out_val 被赋值为对应值并返回 1;否则返回 0
|
||||
*/
|
||||
#define map_get(map, _key, out_val) \
|
||||
(({ \
|
||||
int _found = 0; \
|
||||
if ((map).cap > 0) { \
|
||||
usize _mask = (map).cap - 1; \
|
||||
usize _idx = (map).hash(_key) & _mask; \
|
||||
while ((map).data[_idx].state != __MAP_SLOT_EMPTY) { \
|
||||
if ((map).data[_idx].state == __MAP_SLOT_OCCUPIED && \
|
||||
(map).cmp((map).data[_idx].key, _key) == 0) { \
|
||||
*out_val = (map).data[_idx].val; \
|
||||
_found = 1; \
|
||||
break; \
|
||||
} \
|
||||
_idx = (_idx + 1) & _mask; \
|
||||
} \
|
||||
} \
|
||||
_found; \
|
||||
}))
|
||||
#define map_get(map, _key, out_val) \
|
||||
(({ \
|
||||
int _found = 0; \
|
||||
if ((map).cap > 0) { \
|
||||
usize _mask = (map).cap - 1; \
|
||||
usize _idx = (map).hash(_key) & _mask; \
|
||||
while ((map).data[_idx].state != __MAP_SLOT_EMPTY) { \
|
||||
if ((map).data[_idx].state == __MAP_SLOT_OCCUPIED && \
|
||||
(map).cmp((map).data[_idx].key, _key) == 0) { \
|
||||
*out_val = (map).data[_idx].val; \
|
||||
_found = 1; \
|
||||
break; \
|
||||
} \
|
||||
_idx = (_idx + 1) & _mask; \
|
||||
} \
|
||||
} \
|
||||
_found; \
|
||||
}))
|
||||
|
||||
/**
|
||||
* 删除指定键
|
||||
*/
|
||||
#define map_del(map, _key) \
|
||||
do { \
|
||||
if ((map).cap == 0) \
|
||||
break; \
|
||||
usize _mask = (map).cap - 1; \
|
||||
usize _idx = (map).hash(_key) & _mask; \
|
||||
while ((map).data[_idx].state != __MAP_SLOT_EMPTY) { \
|
||||
if ((map).data[_idx].state == __MAP_SLOT_OCCUPIED && \
|
||||
(map).cmp((map).data[_idx].key, _key) == 0) { \
|
||||
(map).data[_idx].state = __MAP_SLOT_DELETED; \
|
||||
--(map).size; \
|
||||
break; \
|
||||
} \
|
||||
_idx = (_idx + 1) & _mask; \
|
||||
} \
|
||||
} while (0)
|
||||
#define map_del(map, _key) \
|
||||
do { \
|
||||
if ((map).cap == 0) \
|
||||
break; \
|
||||
usize _mask = (map).cap - 1; \
|
||||
usize _idx = (map).hash(_key) & _mask; \
|
||||
while ((map).data[_idx].state != __MAP_SLOT_EMPTY) { \
|
||||
if ((map).data[_idx].state == __MAP_SLOT_OCCUPIED && \
|
||||
(map).cmp((map).data[_idx].key, _key) == 0) { \
|
||||
(map).data[_idx].state = __MAP_SLOT_DELETED; \
|
||||
--(map).size; \
|
||||
break; \
|
||||
} \
|
||||
_idx = (_idx + 1) & _mask; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* __CORE_MAP_H__ */
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#define __vec_free free
|
||||
#define __vec_memcpy memcpy
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -32,11 +33,11 @@ typedef size_t usize;
|
||||
|
||||
#ifndef LOG_FATAL
|
||||
#include <stdio.h>
|
||||
#define LOG_FATAL(...) \
|
||||
do { \
|
||||
printf(__VA_ARGS__); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
#define LOG_FATAL(...) \
|
||||
do { \
|
||||
printf(__VA_ARGS__); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef Assert
|
||||
@@ -61,12 +62,12 @@ typedef size_t usize;
|
||||
* struct people { VEC(char) name; int age; VEC(struct people) children;
|
||||
* };
|
||||
*/
|
||||
#define VEC(type) \
|
||||
struct { \
|
||||
usize size; \
|
||||
usize cap; \
|
||||
type *data; \
|
||||
}
|
||||
#define VEC(type) \
|
||||
struct { \
|
||||
usize size; \
|
||||
usize cap; \
|
||||
type *data; \
|
||||
}
|
||||
|
||||
/** @defgroup vec_operations 动态数组操作宏 */
|
||||
|
||||
@@ -77,20 +78,20 @@ typedef size_t usize;
|
||||
*
|
||||
* @note 此宏不会分配内存,仅做零初始化
|
||||
*/
|
||||
#define vec_init(vec) \
|
||||
do { \
|
||||
(vec).size = 0, (vec).cap = 0, (vec).data = 0; \
|
||||
} while (0)
|
||||
#define vec_init(vec) \
|
||||
do { \
|
||||
(vec).size = 0, (vec).cap = 0, (vec).data = 0; \
|
||||
} while (0)
|
||||
|
||||
#define vec_realloc(vec, new_cap) \
|
||||
do { \
|
||||
void *data = __vec_realloc((vec).data, new_cap * sizeof(*(vec).data)); \
|
||||
if (!data) { \
|
||||
LOG_FATAL("vector_push: realloc failed\n"); \
|
||||
} \
|
||||
(vec).cap = new_cap; \
|
||||
(vec).data = data; \
|
||||
} while (0)
|
||||
#define vec_realloc(vec, new_cap) \
|
||||
do { \
|
||||
void *data = __vec_realloc((vec).data, new_cap * sizeof(*(vec).data)); \
|
||||
if (!data) { \
|
||||
LOG_FATAL("vector_push: realloc failed\n"); \
|
||||
} \
|
||||
(vec).cap = new_cap; \
|
||||
(vec).data = data; \
|
||||
} while (0)
|
||||
|
||||
#define vec_size(vec) ((vec).size)
|
||||
#define vec_cap(vec) ((vec).cap)
|
||||
@@ -105,15 +106,15 @@ typedef size_t usize;
|
||||
* @note 当容量不足时自动扩容为2倍(初始容量为4)
|
||||
* @warning 内存分配失败时会触发LOG_FATAL
|
||||
*/
|
||||
#define vec_push(vec, value) \
|
||||
do { \
|
||||
if ((vec).size >= (vec).cap) { \
|
||||
usize cap = (vec).cap ? (vec).cap * 2 : 4; \
|
||||
vec_realloc(vec, cap); \
|
||||
} \
|
||||
Assert((vec).data != nullptr); \
|
||||
(vec).data[(vec).size++] = value; \
|
||||
} while (0)
|
||||
#define vec_push(vec, value) \
|
||||
do { \
|
||||
if ((vec).size >= (vec).cap) { \
|
||||
usize cap = (vec).cap ? (vec).cap * 2 : 4; \
|
||||
vec_realloc(vec, cap); \
|
||||
} \
|
||||
Assert((vec).data != nullptr); \
|
||||
(vec).data[(vec).size++] = value; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @def vec_pop(vec)
|
||||
@@ -149,43 +150,43 @@ typedef size_t usize;
|
||||
*
|
||||
* @note 释放后需重新初始化才能再次使用
|
||||
*/
|
||||
#define vec_free(vec) \
|
||||
do { \
|
||||
if ((vec).data == nullptr) \
|
||||
break; \
|
||||
__vec_free((vec).data); \
|
||||
(vec).data = nullptr; \
|
||||
(vec).size = (vec).cap = 0; \
|
||||
} while (0)
|
||||
#define vec_free(vec) \
|
||||
do { \
|
||||
if ((vec).data == nullptr) \
|
||||
break; \
|
||||
__vec_free((vec).data); \
|
||||
(vec).data = nullptr; \
|
||||
(vec).size = (vec).cap = 0; \
|
||||
} while (0)
|
||||
|
||||
#define vec_unsafe_get_data(vec) ((vec).data)
|
||||
|
||||
#define vec_unsafe_from_buffer(vec, buffer, buffer_size) \
|
||||
do { \
|
||||
(vec).size = buffer_size; \
|
||||
(vec).cap = (vec).size; \
|
||||
(vec).data = buffer; \
|
||||
} while (0)
|
||||
#define vec_unsafe_from_buffer(vec, buffer, buffer_size) \
|
||||
do { \
|
||||
(vec).size = buffer_size; \
|
||||
(vec).cap = (vec).size; \
|
||||
(vec).data = buffer; \
|
||||
} while (0)
|
||||
|
||||
#define vec_unsafe_from_static_array(vec, array) \
|
||||
do { \
|
||||
(vec).size = sizeof(array) / sizeof((array)[0]); \
|
||||
(vec).cap = (vec).size; \
|
||||
(vec).data = array; \
|
||||
} while (0)
|
||||
#define vec_unsafe_from_static_array(vec, array) \
|
||||
do { \
|
||||
(vec).size = sizeof(array) / sizeof((array)[0]); \
|
||||
(vec).cap = (vec).size; \
|
||||
(vec).data = array; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @def vec_sized_realloc(vec, elem_size, new_cap)
|
||||
* @brief 内部宏:按 elem_size 重新分配内存
|
||||
*/
|
||||
#define vec_sized_realloc(vec, elem_size, new_cap) \
|
||||
do { \
|
||||
void *new_data = __vec_realloc((vec).data, (new_cap) * (elem_size)); \
|
||||
if (!new_data) \
|
||||
LOG_FATAL("vec_sized_realloc: failed\n"); \
|
||||
(vec).data = new_data; \
|
||||
(vec).cap = new_cap; \
|
||||
} while (0)
|
||||
#define vec_sized_realloc(vec, elem_size, new_cap) \
|
||||
do { \
|
||||
void *new_data = __vec_realloc((vec).data, (new_cap) * (elem_size)); \
|
||||
if (!new_data) \
|
||||
LOG_FATAL("vec_sized_realloc: failed\n"); \
|
||||
(vec).data = new_data; \
|
||||
(vec).cap = new_cap; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @def vec_sized_push(vec, elem_size, src_ptr)
|
||||
@@ -198,24 +199,23 @@ typedef size_t usize;
|
||||
* @note 使用前需确保 vec.data 类型与 src_ptr 无关,内部会按字节拷贝。
|
||||
* 推荐声明时为 `VEC(char)` 或 `VEC(unsigned char)`。
|
||||
*/
|
||||
#define vec_sized_push(vec, elem_size, src_ptr, copy_size) \
|
||||
do { \
|
||||
if ((vec).size >= (vec).cap) { \
|
||||
usize new_cap = (vec).cap ? (vec).cap * 2 : 4; \
|
||||
vec_sized_realloc(vec, elem_size, new_cap); \
|
||||
} \
|
||||
char *slot = (char *)(vec).data + (vec).size * (elem_size); \
|
||||
__vec_memcpy(slot, (src_ptr), (copy_size)); \
|
||||
(vec).size++; \
|
||||
} while (0)
|
||||
#define vec_sized_push(vec, elem_size, src_ptr, copy_size) \
|
||||
do { \
|
||||
if ((vec).size >= (vec).cap) { \
|
||||
usize new_cap = (vec).cap ? (vec).cap * 2 : 4; \
|
||||
vec_sized_realloc(vec, elem_size, new_cap); \
|
||||
} \
|
||||
char *slot = (char *)(vec).data + (vec).size * (elem_size); \
|
||||
__vec_memcpy(slot, (src_ptr), (copy_size)); \
|
||||
(vec).size++; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @def vec_sized_at_ptr(vec, elem_size, idx)
|
||||
* @brief 获取第 idx 个元素的指针(void*)
|
||||
* @return 指向元素的指针,需转换为具体类型使用
|
||||
*/
|
||||
#define vec_sized_at_ptr(vec, elem_size, idx) \
|
||||
((void *)((char *)(vec).data + (idx) * (elem_size)))
|
||||
#define vec_sized_at_ptr(vec, elem_size, idx) ((void *)((char *)(vec).data + (idx) * (elem_size)))
|
||||
|
||||
/**
|
||||
* @def vec_sized_foreach(vec, elem_size, elem_ptr_var, block)
|
||||
@@ -223,24 +223,24 @@ typedef size_t usize;
|
||||
* @param elem_ptr_var 循环内的变量名(void* 类型)
|
||||
* @param block 循环体语句块
|
||||
*/
|
||||
#define vec_sized_foreach(vec, elem_size, elem_ptr_var, block) \
|
||||
do { \
|
||||
for (usize __i = 0; __i < (vec).size; ++__i) { \
|
||||
void *elem_ptr_var = vec_sized_at_ptr(vec, elem_size, __i); \
|
||||
block; \
|
||||
} \
|
||||
} while (0)
|
||||
#define vec_sized_foreach(vec, elem_size, elem_ptr_var, block) \
|
||||
do { \
|
||||
for (usize __i = 0; __i < (vec).size; ++__i) { \
|
||||
void *elem_ptr_var = vec_sized_at_ptr(vec, elem_size, __i); \
|
||||
block; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @def vec_sized_pop(vec, elem_size)
|
||||
* @brief 弹出最后一个元素(仅减小 size,不返回数据)
|
||||
*/
|
||||
#define vec_sized_pop(vec, elem_size) \
|
||||
do { \
|
||||
if ((vec).size == 0) \
|
||||
LOG_FATAL("vec_sized_pop: empty\n"); \
|
||||
(vec).size--; \
|
||||
} while (0)
|
||||
#define vec_sized_pop(vec, elem_size) \
|
||||
do { \
|
||||
if ((vec).size == 0) \
|
||||
LOG_FATAL("vec_sized_pop: empty\n"); \
|
||||
(vec).size--; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @def vec_sized_clear(vec)
|
||||
|
||||
88
stage0/include/log.c
Normal file
88
stage0/include/log.c
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "log.h"
|
||||
|
||||
static inline int log_snprintf(char *s, size_t n, const char *format, ...) {
|
||||
int ret;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
ret = log_vsnprintf(s, n, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int log_default_handler(logger_t *module, log_level_t level, const char *file, int line,
|
||||
const char *func, const char *fmt, ...) {
|
||||
const char *level_str;
|
||||
int offset = 0;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
/* clang-format off */
|
||||
switch (level) {
|
||||
case LOG_LEVEL_DEBUG: level_str = "DEBUG"; break;
|
||||
case LOG_LEVEL_INFO: level_str = "INFO "; break;
|
||||
case LOG_LEVEL_WARN: level_str = "WARN "; break;
|
||||
case LOG_LEVEL_ERROR: level_str = "ERROR"; break;
|
||||
case LOG_LEVEL_FATAL: level_str = "FATAL"; break;
|
||||
case LOG_LEVEL_TRACE: level_str = "TRACE"; break;
|
||||
default: level_str = "NOTSET"; break;
|
||||
}
|
||||
/// @note: 定义 __LOG_NO_COLOR__ 会取消颜色输出
|
||||
#ifndef __LOG_NO_COLOR__
|
||||
const char *color_code;
|
||||
switch (level) {
|
||||
case LOG_LEVEL_DEBUG: color_code = ANSI_FG_CYAN; break;
|
||||
case LOG_LEVEL_INFO: color_code = ANSI_FG_GREEN; break;
|
||||
case LOG_LEVEL_TRACE: color_code = ANSI_FG_BLUE; break;
|
||||
case LOG_LEVEL_WARN: color_code = ANSI_FG_YELLOW; break;
|
||||
case LOG_LEVEL_ERROR: color_code = ANSI_FG_RED; break;
|
||||
case LOG_LEVEL_FATAL: color_code = ANSI_FG_RED ANSI_UNDERLINED; break;
|
||||
default: color_code = ANSI_NONE;
|
||||
}
|
||||
/* clang-format on */
|
||||
offset = log_snprintf(module->buf, sizeof(module->buf),
|
||||
ANSI_BOLD "%s[%s] %s - %s:%d in %s()" ANSI_NONE " ", color_code,
|
||||
level_str, module->name, file, line, func);
|
||||
#else
|
||||
offset = log_snprintf(module->buf, sizeof(module->buf), "[%s] %s - %s:%d in %s() ", level_str,
|
||||
module->name, file, line, func);
|
||||
#endif
|
||||
/* 然后写入用户消息(如果有) */
|
||||
if (fmt && fmt[0]) {
|
||||
log_vsnprintf(module->buf + offset, sizeof(module->buf) - offset, fmt, args);
|
||||
}
|
||||
va_end(args);
|
||||
log_puts(module->buf);
|
||||
// for clangd warning
|
||||
// clang-analyzer-deadcode.DeadStores
|
||||
(void)color_code;
|
||||
(void)level_str;
|
||||
if (level & LOG_LEVEL_FATAL) {
|
||||
log_abort();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
logger_t __default_logger_root = {
|
||||
.name = "root",
|
||||
.level = LOG_LEVEL_ALL,
|
||||
.handler = log_default_handler,
|
||||
};
|
||||
|
||||
void init_logger(logger_t *logger, const char *name) {
|
||||
logger->name = name;
|
||||
logger->handler = log_default_handler;
|
||||
log_set_level(logger, LOG_LEVEL_ALL);
|
||||
}
|
||||
|
||||
void log_set_level(logger_t *logger, int level) {
|
||||
if (logger)
|
||||
logger->level = level;
|
||||
else
|
||||
__default_logger_root.level = level;
|
||||
}
|
||||
|
||||
void log_set_handler(logger_t *logger, log_handler handler) {
|
||||
if (logger)
|
||||
logger->handler = handler;
|
||||
else
|
||||
__default_logger_root.handler = handler;
|
||||
}
|
||||
193
stage0/include/log.h
Normal file
193
stage0/include/log.h
Normal file
@@ -0,0 +1,193 @@
|
||||
/**
|
||||
* @file log.h
|
||||
* @brief 日志系统核心模块(支持多级日志、断言和异常处理)
|
||||
*/
|
||||
|
||||
#ifndef __SCC_LOG_IMPL_H__
|
||||
#define __SCC_LOG_IMPL_H__
|
||||
|
||||
#include "color.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __SCC_LOG_IMPL_USE_STD_IMPL__
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#define log_vsnprintf vsnprintf
|
||||
#define log_puts puts
|
||||
#define log_abort abort
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__ // GCC, Clang
|
||||
#define __scc_log_unreachable() (__builtin_unreachable())
|
||||
#elif defined _MSC_VER // MSVC
|
||||
#define __scc_log_unreachable() (__assume(false))
|
||||
#elif defined __SCC_BUILTIN_UNREACHEABLE__ // The SCC Compiler (my compiler)
|
||||
#define __scc_log_unreachable() (__scc_builtin_unreachable())
|
||||
#else
|
||||
#define __scc_log_unreachable() ((void)0)
|
||||
#endif
|
||||
|
||||
#ifndef log_vsnprintf
|
||||
#define log_vsnprintf(...)
|
||||
#warning "log_vsnprintf not defined"
|
||||
#endif
|
||||
|
||||
#ifndef log_puts
|
||||
#define log_puts(...)
|
||||
#warning "log_puts not defined"
|
||||
#endif
|
||||
|
||||
#ifndef log_abort
|
||||
#define log_abort(...)
|
||||
#warning "log_abort not defined"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 日志级别枚举
|
||||
*
|
||||
* 定义日志系统的输出级别和组合标志位
|
||||
*/
|
||||
typedef enum log_level {
|
||||
LOG_LEVEL_NOTSET = 0, ///< 未设置级别(继承默认配置)
|
||||
LOG_LEVEL_DEBUG = 1 << 0, ///< 调试信息(开发阶段详细信息)
|
||||
LOG_LEVEL_INFO = 1 << 1, ///< 常规信息(系统运行状态)
|
||||
LOG_LEVEL_WARN = 1 << 2, ///< 警告信息(潜在问题提示)
|
||||
LOG_LEVEL_ERROR = 1 << 3, ///< 错误信息(可恢复的错误)
|
||||
LOG_LEVEL_FATAL = 1 << 4, ///< 致命错误(导致程序终止的严重错误)
|
||||
LOG_LEVEL_TRACE = 1 << 5, ///< 追踪(性能追踪或者栈帧追踪)
|
||||
LOG_LEVEL_ALL = 0xFF, ///< 全级别标志(组合所有日志级别)
|
||||
} log_level_t;
|
||||
|
||||
#ifndef LOGGER_MAX_BUF_SIZE
|
||||
#define LOGGER_MAX_BUF_SIZE 512 ///< 单条日志最大缓冲区尺寸
|
||||
#endif
|
||||
|
||||
typedef struct logger logger_t;
|
||||
|
||||
typedef int (*log_handler)(logger_t *module, log_level_t level, const char *file, int line,
|
||||
const char *func, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* @brief 日志器实例结构体
|
||||
*
|
||||
* 每个日志器实例维护独立的配置和缓冲区
|
||||
*/
|
||||
struct logger {
|
||||
const char *name; ///< 日志器名称(用于模块区分)
|
||||
log_level_t level; ///< 当前设置的日志级别
|
||||
union {
|
||||
log_handler handler;
|
||||
void *user_handler;
|
||||
}; ///< 日志处理回调函数
|
||||
void *user_data; ///< 用户自定义数据
|
||||
char buf[LOGGER_MAX_BUF_SIZE]; ///< 格式化缓冲区
|
||||
};
|
||||
|
||||
int log_default_handler(logger_t *module, log_level_t level, const char *file, int line,
|
||||
const char *func, const char *fmt, ...);
|
||||
extern logger_t __default_logger_root;
|
||||
#ifndef LOG_DEFAULT_HANDLER
|
||||
#define LOG_DEFAULT_HANDLER &__default_logger_root
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 初始化日志实例 其余参数设置为默认值
|
||||
* @param[in] logger 日志器实例指针
|
||||
* @param[in] name 日志器名称(nullptr表示获取默认日志器名称)
|
||||
*/
|
||||
void init_logger(logger_t *logger, const char *name);
|
||||
|
||||
/**
|
||||
* @brief 设置日志级别
|
||||
* @param[in] logger 目标日志器实例
|
||||
* @param[in] level 要设置的日志级别(可组合多个级别)
|
||||
*/
|
||||
void log_set_level(logger_t *logger, int level);
|
||||
|
||||
/**
|
||||
* @brief 设置自定义日志处理器
|
||||
* @param[in] logger 目标日志器实例
|
||||
* @param[in] handler 自定义处理函数(nullptr恢复默认处理)
|
||||
*/
|
||||
void log_set_handler(logger_t *logger, log_handler handler);
|
||||
|
||||
#ifndef LOG_MAX_MAROC_BUF_SIZE
|
||||
#define LOG_MAX_MAROC_BUF_SIZE LOGGER_MAX_BUF_SIZE ///< 宏展开缓冲区尺寸
|
||||
#endif
|
||||
|
||||
#define SCC_LOG_HANDLE_ARGS(_module_, _level_, ...) \
|
||||
(_module_), (_level_), __FILE__, __LINE__, __func__, ##__VA_ARGS__
|
||||
|
||||
#define SCC_LOG_IMPL(_module_, _level_, _fmt_, ...) \
|
||||
do { \
|
||||
/* TODO check _module_ is nullptr */ \
|
||||
if ((_module_)->handler && ((_module_)->level & (_level_))) \
|
||||
(_module_)->handler(SCC_LOG_HANDLE_ARGS(_module_, _level_, _fmt_, ##__VA_ARGS__)); \
|
||||
} while (0)
|
||||
|
||||
/* clang-format off */
|
||||
/// @name 模块日志宏
|
||||
/// @{
|
||||
#define MLOG_NOTSET(module, ...)SCC_LOG_IMPL(module, LOG_LEVEL_NOTSET, __VA_ARGS__) ///< 未分类日志
|
||||
#define MLOG_DEBUG(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_DEBUG, __VA_ARGS__) ///< 调试日志(需启用DEBUG级别)
|
||||
#define MLOG_INFO(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_INFO, __VA_ARGS__) ///< 信息日志(常规运行日志)
|
||||
#define MLOG_WARN(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_WARN, __VA_ARGS__) ///< 警告日志(潜在问题)
|
||||
#define MLOG_ERROR(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_ERROR, __VA_ARGS__) ///< 错误日志(可恢复错误)
|
||||
#define MLOG_FATAL(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_FATAL, __VA_ARGS__) ///< 致命错误日志(程序终止前)
|
||||
#define MLOG_TRACE(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_TRACE, __VA_ARGS__) ///< 追踪日志(调用栈跟踪)
|
||||
/// @}
|
||||
|
||||
/// @name 快捷日志宏
|
||||
/// @{
|
||||
#define LOG_NOTSET(...) SCC_LOG_IMPL(LOG_DEFAULT_HANDLER, LOG_LEVEL_NOTSET, __VA_ARGS__) ///< 未分类日志
|
||||
#define LOG_DEBUG(...) SCC_LOG_IMPL(LOG_DEFAULT_HANDLER, LOG_LEVEL_DEBUG, __VA_ARGS__) ///< 调试日志(需启用DEBUG级别)
|
||||
#define LOG_INFO(...) SCC_LOG_IMPL(LOG_DEFAULT_HANDLER, LOG_LEVEL_INFO, __VA_ARGS__) ///< 信息日志(常规运行日志)
|
||||
#define LOG_WARN(...) SCC_LOG_IMPL(LOG_DEFAULT_HANDLER, LOG_LEVEL_WARN, __VA_ARGS__) ///< 警告日志(潜在问题)
|
||||
#define LOG_ERROR(...) SCC_LOG_IMPL(LOG_DEFAULT_HANDLER, LOG_LEVEL_ERROR, __VA_ARGS__) ///< 错误日志(可恢复错误)
|
||||
#define LOG_FATAL(...) SCC_LOG_IMPL(LOG_DEFAULT_HANDLER, LOG_LEVEL_FATAL, __VA_ARGS__) ///< 致命错误日志(程序终止前)
|
||||
#define LOG_TRACE(...) SCC_LOG_IMPL(LOG_DEFAULT_HANDLER, LOG_LEVEL_TRACE, __VA_ARGS__) ///< 追踪日志(调用栈跟踪)
|
||||
/// @}
|
||||
/* clang-format on */
|
||||
|
||||
/**
|
||||
* @def _Assert
|
||||
* @brief 断言检查内部宏
|
||||
* @param cond 检查条件表达式
|
||||
* @param ... 错误信息参数(格式字符串+参数)
|
||||
*/
|
||||
#define _Assert(cond, ...) \
|
||||
((void)((cond) || (__default_logger_root.handler(SCC_LOG_HANDLE_ARGS( \
|
||||
&__default_logger_root, LOG_LEVEL_FATAL, __VA_ARGS__)), \
|
||||
log_abort(), __scc_log_unreachable(), 0)))
|
||||
|
||||
/// @name 断言工具宏
|
||||
/// @{
|
||||
#define __INNERSCC_LOG_IMPL_STR(str) #str
|
||||
#define _SCC_LOG_IMPL_STR(str) __INNERSCC_LOG_IMPL_STR(str)
|
||||
#define AssertFmt(cond, format, ...) \
|
||||
_Assert(cond, "Assertion Failure: " format, ##__VA_ARGS__) ///< 带格式的断言检查
|
||||
#define PanicFmt(format, ...) _Assert(0, "Panic: " format, ##__VA_ARGS__) ///< 立即触发致命错误
|
||||
#define Assert(cond) AssertFmt(cond, "cond is `" _SCC_LOG_IMPL_STR(cond) "`") ///< 基础断言检查
|
||||
#define Panic(...) PanicFmt(__VA_ARGS__) ///< 触发致命错误(带自定义消息)
|
||||
#define TODO() PanicFmt("TODO please implement me") ///< 标记未实现代码(触发致命错误)
|
||||
#define UNREACHABLE() PanicFmt("UNREACHABLE") ///< 触发致命错误(代码不可达)
|
||||
#define FIXME(str) PanicFmt("FIXME " _SCC_LOG_IMPL_STR(str)) ///< 提醒开发者修改代码(触发致命错误)
|
||||
/// @}
|
||||
|
||||
/**
|
||||
* @brief 静态断言(编译时)
|
||||
*
|
||||
* 利用数组大小不能为负的特性
|
||||
* 或使用 _Static_assert (C11)
|
||||
*/
|
||||
#if __STDC_VERSION__ >= 201112L
|
||||
#define StaticAssert _Static_assert
|
||||
#else
|
||||
#define StaticAssert(cond, msg) extern char __static_assertion[(cond) ? 1 : -1]
|
||||
#endif
|
||||
|
||||
#ifdef __SCC_LOG_IMPL_IMPORT_SRC__
|
||||
#include "log.c"
|
||||
#endif
|
||||
|
||||
#endif /* __SCC_LOG_IMPL_H__ */
|
||||
10
stage0/include/utils.h
Normal file
10
stage0/include/utils.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef __UTILS_H__
|
||||
#define __UTILS_H__
|
||||
|
||||
#define __SCC_LOG_IMPL_USE_STD_IMPL__
|
||||
#include "log.h"
|
||||
|
||||
#include "core_map.h"
|
||||
#include "core_vec.h"
|
||||
|
||||
#endif /* __UTILS_H__ */
|
||||
Reference in New Issue
Block a user