stage0
This commit is contained in:
1994
stage0/include/acutest.h
Normal file
1994
stage0/include/acutest.h
Normal file
File diff suppressed because it is too large
Load Diff
175
stage0/include/core_map.h
Normal file
175
stage0/include/core_map.h
Normal file
@@ -0,0 +1,175 @@
|
||||
#ifndef __CORE_MAP_H__
|
||||
#define __CORE_MAP_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef nullptr
|
||||
#define nullptr NULL
|
||||
#endif
|
||||
typedef size_t usize;
|
||||
|
||||
#define MAP_TYPEOF __typeof__
|
||||
|
||||
/* 状态常量 */
|
||||
#define __MAP_SLOT_EMPTY 0
|
||||
#define __MAP_SLOT_OCCUPIED 1
|
||||
#define __MAP_SLOT_DELETED 2
|
||||
|
||||
/* 默认负载因子 factor/128 */
|
||||
#define MAP_DEFAULT_LOAD_FACTOR 70
|
||||
|
||||
/* ---------- 默认哈希/比较函数 ---------- */
|
||||
#define MAP_HASH_INT(k) ((usize)((k) * 2654435761U))
|
||||
#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;
|
||||
}
|
||||
#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(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_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)
|
||||
|
||||
/**
|
||||
* 插入(若键已存在则更新值)
|
||||
* 注意:扩容使用 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)
|
||||
|
||||
/**
|
||||
* 查询:若找到,*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_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__ */
|
||||
258
stage0/include/core_vec.h
Normal file
258
stage0/include/core_vec.h
Normal file
@@ -0,0 +1,258 @@
|
||||
/**
|
||||
* @file vec.h
|
||||
* @brief 动态数组(Dynamic Array)实现
|
||||
*
|
||||
* 提供类型安全的动态数组容器实现,支持自动扩容和基本操作
|
||||
*/
|
||||
|
||||
#ifndef __CORE_VEC_H__
|
||||
#define __CORE_VEC_H__
|
||||
|
||||
#define __CORE_VEC_USE_STD__
|
||||
#ifndef __CORE_VEC_USE_STD__
|
||||
#include "core_log.h"
|
||||
|
||||
#include "core_impl.h"
|
||||
#include "core_type.h"
|
||||
#define __vec_realloc realloc
|
||||
#define __vec_free free
|
||||
#define __vec_memcpy memcpy
|
||||
#else
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef nullptr
|
||||
#define nullptr NULL
|
||||
#endif
|
||||
typedef size_t usize;
|
||||
#define __vec_realloc realloc
|
||||
#define __vec_free free
|
||||
#define __vec_memcpy memcpy
|
||||
|
||||
#ifndef LOG_FATAL
|
||||
#include <stdio.h>
|
||||
#define LOG_FATAL(...) \
|
||||
do { \
|
||||
printf(__VA_ARGS__); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef Assert
|
||||
#include <assert.h>
|
||||
#define Assert(cond) assert(cond)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** @defgroup vec_struct 数据结构定义 */
|
||||
|
||||
/**
|
||||
* @def VEC(type)
|
||||
* @brief 声明向量结构体
|
||||
* @param type 存储的数据类型
|
||||
*
|
||||
* 生成包含size/cap/data三个字段的结构体定义:
|
||||
* - size: 当前元素数量
|
||||
* - cap: 数组容量
|
||||
* - data: 存储数组指针
|
||||
* @example
|
||||
* VEC(char) string; <=> char[dynamic_array] string;
|
||||
* struct people { VEC(char) name; int age; VEC(struct people) children;
|
||||
* };
|
||||
*/
|
||||
#define VEC(type) \
|
||||
struct { \
|
||||
usize size; \
|
||||
usize cap; \
|
||||
type *data; \
|
||||
}
|
||||
|
||||
/** @defgroup vec_operations 动态数组操作宏 */
|
||||
|
||||
/**
|
||||
* @def vec_init(vec)
|
||||
* @brief 初始化向量结构体
|
||||
* @param vec 要初始化的向量结构体变量
|
||||
*
|
||||
* @note 此宏不会分配内存,仅做零初始化
|
||||
*/
|
||||
#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_size(vec) ((vec).size)
|
||||
#define vec_cap(vec) ((vec).cap)
|
||||
#define vec_for(vec, idx) for (usize idx = 0; idx < vec_size(vec); idx += 1)
|
||||
|
||||
/**
|
||||
* @def vec_push(vec, value)
|
||||
* @brief 添加元素到向量末尾
|
||||
* @param vec 目标向量结构体
|
||||
* @param value 要添加的值(需匹配存储类型)
|
||||
*
|
||||
* @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)
|
||||
|
||||
/**
|
||||
* @def vec_pop(vec)
|
||||
* @brief 弹出最后一个元素
|
||||
* @param vec 目标向量结构体
|
||||
* @return 最后元素的引用
|
||||
* @warning 需确保size > 0时使用
|
||||
*/
|
||||
#define vec_pop(vec) ((vec).data[--(vec).size])
|
||||
|
||||
/**
|
||||
* @def vec_at(vec, idx)
|
||||
* @brief 获取指定索引元素
|
||||
* @param vec 目标向量结构体
|
||||
* @param idx 元素索引(0 <= idx < size)
|
||||
* @return 对应元素的引用
|
||||
*/
|
||||
#define vec_at(vec, idx) (((vec).data)[idx])
|
||||
|
||||
/**
|
||||
* @def vec_idx(vec, ptr)
|
||||
* @brief 获取元素指针对应的索引
|
||||
* @param vec 目标向量结构体
|
||||
* @param ptr 元素指针(需在data数组范围内)
|
||||
* @return 元素索引值
|
||||
*/
|
||||
#define vec_idx(vec, ptr) ((ptr) - (vec).data)
|
||||
|
||||
/**
|
||||
* @def vec_free(vec)
|
||||
* @brief 释放向量内存
|
||||
* @param vec 目标向量结构体
|
||||
*
|
||||
* @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_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_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)
|
||||
|
||||
/**
|
||||
* @def vec_sized_push(vec, elem_size, src_ptr)
|
||||
* @brief 添加一个元素(从 src_ptr 拷贝 elem_size 字节)
|
||||
* @param vec VEC(type) 定义的向量变量(type 可为 char 或 void)
|
||||
* @param elem_size 每个元素占用的字节数
|
||||
* @param src_ptr 源数据的指针
|
||||
* @param copy_size 要拷贝的字节数
|
||||
*
|
||||
* @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)
|
||||
|
||||
/**
|
||||
* @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)))
|
||||
|
||||
/**
|
||||
* @def vec_sized_foreach(vec, elem_size, elem_ptr_var, block)
|
||||
* @brief 遍历所有元素
|
||||
* @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)
|
||||
|
||||
/**
|
||||
* @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)
|
||||
|
||||
/**
|
||||
* @def vec_sized_clear(vec)
|
||||
* @brief 清空向量(重置 size = 0,不释放内存)
|
||||
*/
|
||||
#define vec_sized_clear(vec) ((vec).size = 0)
|
||||
|
||||
/**
|
||||
* @def vec_sized_free(vec)
|
||||
* @brief 释放向量内存(与原始 vec_free 相同,可复用)
|
||||
* @note 注意:如果元素内部有堆资源,需在释放前自行遍历调用析构函数。
|
||||
*/
|
||||
#define vec_sized_free(vec) vec_free(vec)
|
||||
|
||||
#endif /* __CORE_VEC_H__ */
|
||||
Reference in New Issue
Block a user