This commit is contained in:
2026-05-19 11:49:22 +08:00
commit add7af4222
96 changed files with 8635 additions and 0 deletions
+125
View File
@@ -0,0 +1,125 @@
#include <arena.h>
#include <string.h>
#include <os_align.h>
#include "os_macros.h"
#define IS_POWER_OF_2(n) ((n) != 0 && (((n) & ((n) - 1)) == 0))
#define DEFAULT_ALIGNMENT OS_ALIGN_SIZE
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
static
os_uintptr_t align_forward(os_uintptr_t ptr, os_size_t align) {
os_uintptr_t p, a, modulo;
OS_ASSERT(IS_POWER_OF_2(align));
p = ptr;
a = (os_uintptr_t )align;
// Same as (p % a) but faster as 'a' is a power of two
modulo = p & (a-1);
if (modulo != 0) {
// If 'p' address is not aligned, push the address to the
// next value which is aligned
p += a - modulo;
}
return p;
}
static void *arena_alloc_align(arena_t *a, os_size_t size, os_size_t align) {
// Align 'curr_offset' forward to the specified alignment
os_uintptr_t curr_ptr = (os_uintptr_t) a->buf + (os_uintptr_t) a->curr_offset;
os_uintptr_t offset = align_forward(curr_ptr, align);
offset -= (os_uintptr_t) a->buf; // Change to relative offset
// Check to see if the backing memory has space left
if (offset+size <= a->buf_size) {
void *ptr = &a->buf[offset];
a->prev_offset = offset;
a->curr_offset = offset+size;
// Zero new memory by default
memset(ptr, 0, size);
return ptr;
}
// Return NULL if the arena is out of memory (or handle differently)
return NULL;
}
static void *arena_resize_align(arena_t *a, void *old_memory, size_t old_size, size_t new_size, size_t align) {
unsigned char *old_mem = (unsigned char *)old_memory;
OS_ASSERT(IS_POWER_OF_2(align));
if (old_mem == NULL || old_size == 0) {
return arena_alloc_align(a, new_size, align);
} else if (a->buf <= old_mem && old_mem < a->buf+a->buf_size) {
if (a->buf+a->prev_offset == old_mem) {
a->curr_offset = a->prev_offset + new_size;
if (new_size > old_size) {
// Zero the new memory by default
memset(&a->buf[a->curr_offset], 0, new_size-old_size);
}
return old_memory;
} else {
void *new_memory = arena_alloc_align(a, new_size, align);
size_t copy_size = old_size < new_size ? old_size : new_size;
// Copy across old memory to the new memory
memmove(new_memory, old_memory, copy_size);
return new_memory;
}
} else {
OS_ASSERT(0 && "Memory is out of bounds of the buffer in this arena");
return NULL;
}
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
void arena_init(arena_t* self, uint8_t * buf, os_size_t buf_size){
self->buf = buf;
self->buf_size = buf_size;
self->prev_offset = 0;
self->curr_offset = 0;
}
void* arena_alloc(arena_t* self, os_size_t size){
return arena_alloc_align(self, size, DEFAULT_ALIGNMENT);
}
void* arena_realloc(arena_t* self, void* old, os_size_t old_size, os_size_t new_size){
return arena_resize_align(self, old, old_size, new_size, DEFAULT_ALIGNMENT);
}
void arena_free(arena_t* self, void* ptr)
{}
void arean_destroy(arena_t* self){
self->curr_offset = 0;
self->prev_offset = 0;
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
temp_arena_memory_t temp_arena_memory_begin(arena_t *a) {
temp_arena_memory_t temp;
temp.arena = a;
temp.prev_offset = a->prev_offset;
temp.curr_offset = a->curr_offset;
return temp;
}
void temp_arena_memory_end(temp_arena_memory_t temp) {
temp.arena->prev_offset = temp.prev_offset;
temp.arena->curr_offset = temp.curr_offset;
}
+46
View File
@@ -0,0 +1,46 @@
#ifndef INCLUDED_ARENA_H
#define INCLUDED_ARENA_H
#ifndef INCLUDED_OS_TYPES_H
#include <os_types.h>
#endif /*INCLUDED_OS_TYPES_H*/
/* ------------------------------------------------------------------------------------------------------------------ */
/* https://www.gingerbill.org/article/2019/02/08/memory-allocation-strategies-002/ */
typedef struct arena_t{
uint8_t * buf;
os_size_t buf_size;
os_size_t prev_offset;
os_size_t curr_offset;
}arena_t;
typedef struct temp_arena_memory_t {
arena_t *arena;
size_t prev_offset;
size_t curr_offset;
}temp_arena_memory_t;
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
void arena_init(arena_t* self, uint8_t * buf, os_size_t buf_size);
void* arena_alloc(arena_t* self, os_size_t size);
void* arena_realloc(arena_t* self, void* old, os_size_t old_size, os_size_t new_size);
// 不支持的操作
//void arena_free(arena_t* self, void* ptr);
void arean_destroy(arena_t* self);
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
temp_arena_memory_t temp_arena_memory_begin(arena_t *a);
void temp_arena_memory_end(temp_arena_memory_t temp);
#endif /*INCLUDED_ARENA_H*/
+285
View File
@@ -0,0 +1,285 @@
#include <buddy.h>
#include <os_macros.h>
#include <string.h>
#include <os_compiler.h>
#define IS_POWER_OF_2(n) ((n) != 0 && (((n) & ((n) - 1)) == 0))
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
OS_STATIC_FORCE_INLINE
buddy_block_t* buddy_block_next(buddy_block_t* block){
return (buddy_block_t*)((uint8_t*)block + block->size);
}
static
buddy_block_t *buddy_block_split(buddy_block_t *block, size_t size) {
if (block != NULL && size != 0) {
// Recursive split
while (size < block->size) {
size_t sz = block->size >> 1;
block->size = sz;
block = buddy_block_next(block);
block->size = sz;
block->is_free = OS_TRUE;
}
if (size <= block->size) {
return block;
}
}
// Block cannot fit the requested allocation size
return NULL;
}
static
buddy_block_t *buddy_block_find_best(buddy_block_t *head, buddy_block_t *tail, size_t size) {
// Assumes size != 0
buddy_block_t *best_block = NULL;
buddy_block_t *block = head; // Left Buddy
buddy_block_t *buddy = buddy_block_next(block); // Right Buddy
// The entire memory section between head and tail is free,
// just call 'buddy_block_split' to get the allocation
if (buddy == tail && block->is_free) {
return buddy_block_split(block, size);
}
// Find the block which is the 'best_block' to requested allocation sized
while (block < tail && buddy < tail) { // make sure the buddies are within the range
// If both buddies are free, coalesce them together
// NOTE: this is an optimization to reduce fragmentation
// this could be completely ignored
if (block->is_free && buddy->is_free && block->size == buddy->size) {
block->size <<= 1;
if (size <= block->size && (best_block == NULL || block->size <= best_block->size)) {
best_block = block;
}
block = buddy_block_next(buddy);
if (block < tail) {
// Delay the buddy block for the next iteration
buddy = buddy_block_next(block);
}
continue;
}
if (block->is_free && size <= block->size &&
(best_block == NULL || block->size <= best_block->size)) {
best_block = block;
}
if (buddy->is_free && size <= buddy->size &&
(best_block == NULL || buddy->size < best_block->size)) {
// If each buddy are the same size, then it makes more sense
// to pick the buddy as it "bounces around" less
best_block = buddy;
}
if (block->size <= buddy->size) {
block = buddy_block_next(buddy);
if (block < tail) {
// Delay the buddy block for the next iteration
buddy = buddy_block_next(block);
}
} else {
// Buddy was split into smaller blocks
block = buddy;
buddy = buddy_block_next(buddy);
}
}
if (best_block != NULL) {
// This will handle the case if the 'best_block' is also the perfect fit
return buddy_block_split(best_block, size);
}
// Maybe out of memory
return NULL;
}
OS_STATIC_FORCE_INLINE
os_size_t align_forward_size(os_size_t ptr, os_size_t align) {
os_size_t a, p, modulo;
OS_ASSERT(IS_POWER_OF_2((os_uintptr_t)align));
a = align;
p = ptr;
modulo = p & (a-1);
if (modulo != 0) {
p += a - modulo;
}
return p;
}
OS_STATIC_FORCE_INLINE
os_size_t buddy_block_size_required(buddy_t *b, size_t size) {
os_size_t actual_size = b->alignment;
size += sizeof(buddy_block_t);
size = align_forward_size(size, b->alignment);
while (size > actual_size) {
actual_size <<= 1;
}
return actual_size;
}
static
void buddy_block_coalescence(buddy_block_t *head, buddy_block_t *tail) {
for (;;) {
// Keep looping until there are no more buddies to coalesce
buddy_block_t *block = head;
buddy_block_t *buddy = buddy_block_next(block);
#if 0
// 原版有bug
bool no_coalescence = OS_TRUE;
while (block < tail && buddy < tail) { // make sure the buddies are within the range
if (block->is_free && buddy->is_free && block->size == buddy->size) {
// Coalesce buddies into one
block->size <<= 1;
block = buddy_block_next(block);
if (block < tail) {
buddy = buddy_block_next(block);
no_coalescence = C_FALSE;
}
} else if (block->size < buddy->size) {
// The buddy block is split into smaller blocks
block = buddy;
buddy = buddy_block_next(buddy);
} else {
block = buddy_block_next(buddy);
if (block < tail) {
// Leave the buddy block for the next iteration
buddy = buddy_block_next(block);
}
}
}
#endif
bool no_coalescence = OS_TRUE;
while (block < tail && buddy < tail) { // make sure the buddies are within the range
if (block->is_free && buddy->is_free && block->size == buddy->size) {
// Coalesce buddies into one
block->size <<= 1;
// block = buddy_block_next(buddy);
if (block < tail) {
buddy = buddy_block_next(block);
no_coalescence = OS_FALSE;
}
} else if (block->size <= buddy->size) {
block = buddy_block_next(buddy);
if (block < tail) {
// Leave the buddy block for the next iteration
buddy = buddy_block_next(block);
}
} else {
// The buddy block is split into smaller blocks
block = buddy;
buddy = buddy_block_next(buddy);
}
}
if (no_coalescence) {
return;
}
}
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
void buddy_init(buddy_t* self, void* block, os_size_t block_size, os_size_t alignment){
OS_ASSERT(block != NULL);
OS_ASSERT(IS_POWER_OF_2(block_size) && "size is not a power-of-two");
OS_ASSERT(IS_POWER_OF_2(alignment) && "alignment is not a power-of-two");
// The minimum alignment depends on the size of the `budy_block_t` header
alignment = OS_MAX(alignment, sizeof(buddy_block_t));
// if (alignment < sizeof(buddy_block_t)) {
// alignment = sizeof(buddy_block_t);
// }
OS_ASSERT((uintptr_t)block % alignment == 0 && "block is not aligned to minimum alignment");
self->head = (buddy_block_t *)block;
self->head->size = block_size;
self->head->is_free = OS_TRUE;
// The tail here is a sentinel value and not a true block
self->tail = buddy_block_next(self->head);
self->alignment = alignment;
}
void buddy_destroy(buddy_t* self){
self->head = 0;
self->tail = 0;
self->alignment = 0;
}
void* buddy_alloc(buddy_t* b, os_size_t size){
if (size != 0) {
size_t actual_size = buddy_block_size_required(b, size);
buddy_block_t *found = buddy_block_find_best(b->head, b->tail, actual_size);
if (found == NULL) {
// Try to coalesce all the free buddy blocks and then search again
buddy_block_coalescence(b->head, b->tail);
found = buddy_block_find_best(b->head, b->tail, actual_size);
}
if (found != NULL) {
found->is_free = OS_FALSE;
return (void *)((uint8_t *)found + b->alignment);
}
// Out of memory (possibly due to too much internal fragmentation)
}
return NULL;
}
void* buddy_calloc(buddy_t* b, os_size_t count, os_size_t size){
void* mem = buddy_alloc(b, size * count);
if(mem){
memset(mem, 0, size);
}
return mem;
}
void* buddy_realloc(buddy_t* self, void* ptr, os_size_t size){
void* mem = buddy_alloc(self, size);
if(!mem){
return NULL;
}
buddy_block_t *block =(buddy_block_t *)((uint8_t *)ptr - self->alignment);
size = OS_MIN(size, block->size);
memcpy(mem, ptr, size);
buddy_free(self, ptr);
return mem;
}
void buddy_free(buddy_t* b, void* data){
if (data != NULL) {
buddy_block_t *block;
OS_ASSERT(b->head <= (buddy_block_t*)data);
OS_ASSERT((buddy_block_t*)data < b->tail);
block = (buddy_block_t *)((uint8_t *)data - b->alignment);
block->is_free = OS_TRUE;
// NOTE: Coalescence could be done now but it is optional
// buddy_block_coalescence(b->head, b->tail);
}
}
+37
View File
@@ -0,0 +1,37 @@
#ifndef INCLUDED_BUDDY_H
#define INCLUDED_BUDDY_H
#ifndef INCLUDED_OS_TYPES_H
#include <os_types.h>
#endif /*INCLUDED_OS_TYPES_H*/
/* ------------------------------------------------------------------------------------------------------------------ */
/* https://www.gingerbill.org/article/2021/12/02/memory-allocation-strategies-006/ */
typedef struct buddy_block_t{
os_size_t size;
os_bool_t is_free;
}buddy_block_t;
typedef struct buddy_t{
buddy_block_t* head;
buddy_block_t* tail;
int alignment;
}buddy_t;
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
void buddy_init(buddy_t* self, void* buf, os_size_t buf_size /*POWER_OF_2*/, os_size_t alignment /*POWER_OF_2*/);
void buddy_destroy(buddy_t* self);
void* buddy_alloc(buddy_t* self, os_size_t size);
void* buddy_calloc(buddy_t* b, os_size_t count, os_size_t size);
void* buddy_realloc(buddy_t* self, void* ptr, os_size_t size);
void buddy_free(buddy_t* self, void* ptr);
#endif /*INCLUDED_BUDDY_H*/
+30
View File
@@ -0,0 +1,30 @@
#include <os_memory.h>
#include "buddy.h"
#include "os_align.h"
#include "os_compiler.h"
// 默认使用 buddy
static buddy_t s_buddy;
OS_WEAK
void os_memory_init(void* block, os_size_t block_size){
buddy_init(&s_buddy, block, block_size, OS_ALIGN_SIZE);
}
void* os_memory_alloc(os_size_t nBytes, const char* file, os_size_t line){
return buddy_alloc(&s_buddy, nBytes);
}
void* os_memory_realloc(void* ptr, os_size_t nBytes, const char* file, os_size_t line){
return buddy_realloc(&s_buddy, ptr, nBytes);
}
void* os_memory_calloc(os_size_t nCount, os_size_t nBytes, const char* file, os_size_t line){
return buddy_calloc(&s_buddy, nCount, nBytes);
}
void os_memory_free(void* ptr, const char* file, os_size_t line){
if(!ptr) return;
buddy_free(&s_buddy, ptr);
}
+106
View File
@@ -0,0 +1,106 @@
#include <debounce.h>
void Debounce_Init(Debounce_t* self){
self->state = kButtonState_IDLE;
self->debounce_cnt = 0;
self->long_press_cnt = 0;
self->double_click_cnt = 0;
self->is_pressed = 0;
self->last_pressed = 0;
}
ButtonEvent_t Debounce_Handle(Debounce_t* self, uint8_t cur_state){
ButtonEvent_t event = kButtonEvent_NONE;
self->is_pressed = cur_state;
switch (self->state) {
case kButtonState_IDLE:{
if(cur_state == 1){
self->state = kButtonState_DEBOUNCE;
self->debounce_cnt = 0;
}
break;
}
case kButtonState_DEBOUNCE:{
if(cur_state==1){
self->debounce_cnt++;
if(self->debounce_cnt >= DEBOUNCE_TICKS){
self->state = kButtonState_PRESS;
self->debounce_cnt = 0;
event = kButtonEvent_PRESS; /* 触发下按事件 */
}
}else{
self->state = kButtonState_IDLE;
}
break;
}
case kButtonState_PRESS:{
if(cur_state==1){
self->long_press_cnt++;
if(self->long_press_cnt >= DEBOUNCE_LONG_TICKS){
self->state = kButtonState_LONG_PRESS;
event = kButtonEvent_LONG_PRESS;
}
}else{
// 第一击释放,进入释放消抖,防止触摸屏抖动误判
self->state = kButtonState_RELEASE_DEBOUNCE;
self->debounce_cnt = 0;
self->long_press_cnt = 0;
}
break;
}
case kButtonState_LONG_PRESS:{
if(cur_state==0){
self->state = kButtonState_IDLE;
self->long_press_cnt = 0;
event = kButtonEvent_RELEASE;
}
break;
}
case kButtonState_WAIT_DOUBLE:{
if(cur_state==1){ /* 在规定时间内再次按下,判定为双击 */
self->state = kButtonState_DOUBLE_DEBOUNCE; /* 去除第二次抖动 */
self->debounce_cnt = 0;
}else{
self->double_click_cnt++;
if(self->double_click_cnt>=DEBOUNCE_DOUBLE_TICKS){ // 超时未按下,判定为普通的独立单击
self->state = kButtonState_LONG_PRESS;
event = kButtonEvent_CLICK;
self->double_click_cnt = 0;
}
}
break;
}
case kButtonState_DOUBLE_DEBOUNCE:{
if(cur_state==1){
self->debounce_cnt++;
if(self->debounce_cnt >= DEBOUNCE_TICKS){
self->state = kButtonState_LONG_PRESS; /* 等待释放 */
self->debounce_cnt = 0;
event = kButtonEvent_DOUBLE_CLICK; /* 确认双击 */
}
}else{
self->state = kButtonState_IDLE;
}
break;
}
case kButtonState_RELEASE_DEBOUNCE:{
if(cur_state==0){
self->debounce_cnt++;
if(self->debounce_cnt >= DEBOUNCE_TICKS){
// 确认释放,开始计时等待第二击
self->state = kButtonState_WAIT_DOUBLE;
self->double_click_cnt = 0;
}
}else{
self->state = kButtonState_PRESS; // 抖动,返回按下状态
}
break;
}
default: break;
}
self->last_pressed = cur_state;
return event;
}
+64
View File
@@ -0,0 +1,64 @@
#ifndef INCLUDED_DEBOUNCE_H
#define INCLUDED_DEBOUNCE_H
#ifndef INCLUDED_STDINT_H
#define INCLUDED_STDINT_H
#include <stdint.h>
#endif /*INCLUDED_STDINT_H*/
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
typedef enum {
kButtonEvent_NONE = 0,
kButtonEvent_PRESS,
kButtonEvent_CLICK,
kButtonEvent_DOUBLE_CLICK,
kButtonEvent_LONG_PRESS,
kButtonEvent_RELEASE,
}ButtonEvent_t;
typedef enum{
kButtonState_IDLE = 0,
kButtonState_DEBOUNCE, /* 按下消抖 */
kButtonState_PRESS, /* 确认按下,等待释放或长按 */
kButtonState_LONG_PRESS, /* 处于长按状态 */
kButtonState_WAIT_DOUBLE, /* 等待第二次按下 */
kButtonState_DOUBLE_DEBOUNCE, /* 第二次消抖 */
kButtonState_RELEASE_DEBOUNCE, /* 释放消抖 */
}ButtonState_t;
typedef struct {
ButtonState_t state;
uint8_t debounce_cnt; /* 消抖计数器 */
uint16_t long_press_cnt; /* 长按计数器 */
uint16_t double_click_cnt; /* 双击等待计数器 */
uint8_t is_pressed; /* 经过消抖后当前的电平: (1:按下, 0:松开) */
uint8_t last_pressed; /* 上一次物理电平 */
}Debounce_t;
#define DEBOUNCE_INIT {kButtonState_IDLE, 0, 0, 0, 0, 0}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
// 核心参数配置(基于 10ms 状态机轮询周期)
#define DEBOUNCE_TICKS 3 // 消抖时间: 3 * 10ms = 30ms
#define DEBOUNCE_LONG_TICKS 150 // 长按判定: 150 * 10ms = 1.5s
#define DEBOUNCE_DOUBLE_TICKS 35 // 双击间隔: 35 * 10ms = 350ms
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
void Debounce_Init(Debounce_t* self);
/**
* @brief 状态机核心处理函数(需在 10ms 定时器中断或主循环定时中调用)
* @param self: 消抖结构体指针
* @param cur_state: 当前按键状态,1:按下, 0:松开
* @return 检测到的事件类型
*/
ButtonEvent_t Debounce_Handle(Debounce_t* self, uint8_t cur_state);
#endif /*INCLUDED_DEBOUNCE_H*/
+399
View File
@@ -0,0 +1,399 @@
#include <fifo.h>
#include <os_macros.h>
#include <ctype.h> // isspace
#include <limits.h> // ULONG_MAX
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
// 在尾部写入数据
os_err_t fifo_put(fifo_t* self, uint8_t data){
os_size_t write_idx = self->write_idx;
os_size_t next_write_idx = write_idx + 1;
if(next_write_idx >= self->buffer_size){
next_write_idx = 0;
}
if(next_write_idx == self->read_idx){
return OS_ERR_FULL;
}
self->buffer[write_idx] = data;
self->write_idx = next_write_idx;
return OS_ERR_OK;
}
// 从头部获取数据
os_err_t fifo_get(fifo_t* self, uint8_t* data){
os_size_t read_idx = self->read_idx;
if(read_idx==self->write_idx){
return OS_ERR_EMPTY;
}
if(data){
*data = self->buffer[read_idx];
}
os_size_t next_read_idx = read_idx + 1;
if(next_read_idx >= self->buffer_size){
next_read_idx = 0;
}
self->read_idx = next_read_idx;
return OS_ERR_OK;
}
// 批量写入数据
os_size_t fifo_write(fifo_t* self, uint8_t* data, os_size_t size){
os_size_t i;
for(i=0; i<size; i++){
if(fifo_put(self, data[i])!=OS_ERR_OK){
break;
}
}
return i;
}
// 批量读取数据
os_size_t fifo_read(fifo_t* self, uint8_t* buf, os_size_t size){
os_size_t i;
for(i=0; i<size; i++){
if(fifo_get(self, buf++)!=OS_ERR_OK){
break;
}
}
return i;
}
os_size_t fifo_write_fast(fifo_t* rb, const uint8_t * data, os_size_t len){
if (rb == NULL || data == NULL || len == 0) {
return 0;
}
/* 如果写入数据超过剩余空间,则只写入剩余空间部分(或者可以选择报错/覆盖,这里选择截断) */
os_size_t free_sp = fifo_space(rb);
if (len > free_sp) {
len = free_sp;
}
if (len == 0) {
// 没有空间了
return 0;
}
// 分段写入
// buf_size: 8
// 0, 1, 2, 3, 4, 5, 6, 7
// r w
// w r
os_size_t write_idx = rb->write_idx;
os_size_t read_idx = rb->read_idx;
os_size_t size = rb->buffer_size;
if(write_idx > read_idx){
os_size_t first_part = size - write_idx;
if(first_part >= len){
// 一次就可以拷贝完成
memcpy(&rb->buffer[write_idx], data, first_part);
}else{
// 分成两个部分
memcpy(&rb->buffer[write_idx], data, first_part);
os_size_t second_part = len - first_part;
memcpy(&rb->buffer, &data[first_part], second_part);
}
}else{
// 这里不会有 write_idx == read_idx 的情况,这种情况,free_sp=0
// 前面已经计算过 len 就是最多可以存下的字节数,因此这里直接拷贝
memcpy(&rb->buffer[write_idx], data, len);
}
rb->write_idx = (write_idx + len) % size;
return len;
}
os_size_t fifo_read_fast(fifo_t* rb, uint8_t * data, os_size_t len){
if (rb == NULL || data == NULL || len == 0) {
return 0;
}
/* 如果读取长度超过有效数据长度,则只读取有效部分 */
os_size_t data_sz = fifo_count(rb);
if (len > data_sz) {
len = data_sz;
}
if (len == 0) {
return 0;
}
os_size_t read_idx = rb->read_idx;
os_size_t write_idx = rb->write_idx;
os_size_t size = rb->buffer_size;
// 分段读取
// buf_size: 8
// 0, 1, 2, 3, 4, 5, 6, 7
// r w
// w r
if(write_idx > read_idx){
memcpy(&data, &rb->buffer[read_idx], len);
}else{
os_size_t first_part = size - read_idx;
if(first_part >= len){
// 一次就可以拷贝完成
memcpy(data, &rb->buffer[read_idx], first_part);
}else{
// 分成两个部分
memcpy(data, &rb->buffer[read_idx], first_part);
os_size_t second_part = len - first_part;
memcpy(&data[first_part], &rb->buffer, second_part);
}
}
rb->read_idx = (read_idx + len) % size;
return len;
}
os_err_t fifo_peek_at(fifo_t* self, os_size_t offset, uint8_t * data){
os_size_t data_sz = fifo_count(self);
if(offset >= data_sz){
return OS_ERR_FULL;
}
if(data){
os_size_t index = (self->read_idx + offset) % self->buffer_size;
*data = self->buffer[index];
}
return OS_ERR_OK;
}
os_size_t fifo_peek_bulk(fifo_t* rb, os_size_t offset, uint8_t* data, os_size_t len){
if (rb == NULL || data == NULL || len == 0) {
return 0;
}
/* 如果读取长度超过有效数据长度,则只读取有效部分 */
os_size_t data_sz = fifo_count(rb);
if(offset >= data_sz){
return 0;
}
if (len > (data_sz - offset)) {
len = data_sz - offset;
}
if (len == 0) {
return 0;
}
os_size_t size = rb->buffer_size;
os_size_t read_idx = (rb->read_idx + offset) % size;
os_size_t write_idx = rb->write_idx;
// 分段读取
// buf_size: 8
// 0, 1, 2, 3, 4, 5, 6, 7
// r w
// w r
if(write_idx > read_idx){
memcpy(&data, &rb->buffer[read_idx], len);
}else{
os_size_t first_part = size - read_idx;
if(first_part >= len){
// 一次就可以拷贝完成
memcpy(data, &rb->buffer[read_idx], first_part);
}else{
// 分成两个部分
memcpy(data, &rb->buffer[read_idx], first_part);
os_size_t second_part = len - first_part;
memcpy(&data[first_part], &rb->buffer, second_part);
}
}
return len;
}
int fifo_memcmp(fifo_t *rb, os_size_t offset, const void *ptr, os_size_t len) {
os_size_t data_sz = fifo_count(rb);
OS_ASSERT(offset < data_sz);
OS_ASSERT(ptr);
if (len > (data_sz - offset)) {
// 如果请求比较的长度超过缓冲区现有数据量,可根据需求返回错误或只比较现有部分
// 这里假设调用者确保len <= fifo_count,或者我们只比较有效部分
len = data_sz - offset;
}
uint8_t rb_byte=0xff;
const uint8_t *external_ptr = (const uint8_t *)ptr;
for (os_size_t i = 0; i < len; i++) {
fifo_peek_at(rb, i + offset, &rb_byte);
if (rb_byte != external_ptr[i]) {
return (int)rb_byte - (int)external_ptr[i];
}
}
return 0;
}
/**
* 在FIFO中查找特定模式
* @return: 找到则返回模式起始位置相对于head的偏移量,未找到返回-1
*/
os_size_t fifo_find(fifo_t *rb, os_size_t offset, const void *pattern, os_size_t pattern_len) {
if (!rb || !pattern || pattern_len == 0) {
return -1u;
}
os_size_t data_size = fifo_count(rb);
if(offset > data_size){
return -1u; // 开始查找位置错误了
}
if (pattern_len > (data_size - offset) ) {
return -1u; // 模式长度超过缓冲区数据量,不可能找到
}
// 遍历缓冲区中所有可能的起始位置
// 最大起始偏移为 count - pattern_len
os_size_t max_offset = data_size - offset - pattern_len;
for (os_size_t i = 0; i <= max_offset; i++) {
// 构造一个临时的“视图”或使用辅助函数比较从offset开始的pattern_len个字节
// 由于fifo_memcmp是从head开始比较,我们需要一种方法从任意offset开始比较
// 方法:逐字节比较
os_bool_t match = OS_TRUE;
const uint8_t *pat = (const uint8_t *)pattern;
for (os_size_t j = 0; j < pattern_len; j++) {
uint8_t rb_byte;
if (fifo_peek_at(rb, i + offset + j, &rb_byte)!=OS_ERR_OK) {
match = OS_FALSE;
break;
}
if (rb_byte != pat[j]) {
match = OS_FALSE;
break;
}
}
if (match) {
return i;
}
}
return -1u;
}
unsigned long fifo_strtoul(fifo_t* self, os_size_t* endptr /*从哪里开始转换*/, int base) {
os_size_t idx = endptr?(*endptr):0;
unsigned long acc = 0;
uint8_t c = 0xff;
unsigned long cutoff;
int neg = 0, any, cutlim;
((void)neg);
fifo_peek_at(self, idx, &c);
// 1. 跳过前导空白字符
while (isspace((unsigned char)c)) {
idx++;
}
// 2. 处理可选的正负号 (strtoul 忽略负号,但会消耗它)
if (/* *s == '-'*/ fifo_offset_is(self, idx, '-')) {
neg = 1;
idx++;
} else if (/* *s == '+' */ fifo_offset_is(self, idx, '+')) {
idx++;
}
// 3. 确定基数
if (base == 0) {
if (/* *s == '0' */ fifo_offset_is(self, idx, '0')) {
if (/* *(s + 1) == 'x' || *(s + 1) == 'X' */
fifo_offset_is(self, idx+1, 'x')
|| fifo_offset_is(self, idx+1, 'X') )
{
base = 16;
idx += 2; // 跳过 0x
} else {
base = 8;
idx++; // 跳过 0
}
} else {
base = 10;
}
} else if (base == 16) {
if (/* *s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X') */
fifo_offset_is(self, idx, '0')
&& (fifo_offset_is(self, idx+1, 'x') || fifo_offset_is(self, idx+1, 'X')) )
{
idx += 2;
}
}
// 4. 预计算溢出检查边界
cutoff = ULONG_MAX / (unsigned long)base;
cutlim = ULONG_MAX % (unsigned long)base;
// 5. 转换数字
any = 0; // 标记是否已读取到有效数字
for (; ; idx++) {
// c = (unsigned char)*s;
fifo_peek_at(self, idx, &c);
// 将字符转换为数值
if (c >= '0' && c <= '9') {
c -= '0';
} else if (c >= 'A' && c <= 'Z') {
c -= 'A' - 10;
} else if (c >= 'a' && c <= 'z') {
c -= 'a' - 10;
} else {
break; // 非数字字符,停止解析
}
// 检查字符是否在当前基数范围内
if (c >= base) {
break;
}
// 检查溢出
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
break;
} else {
any = 1;
acc *= base;
acc += c;
}
}
// 6. 处理结果和错误
if (any < 0) {
acc = ULONG_MAX;
// errno = ERANGE;
} else if (!any) {
// 没有进行任何转换
// if (endptr) {
// *endptr = (char *)nptr;
// }
return 0;
}
// 设置 endptr 指向第一个未转换的字符
if (endptr) {
*endptr = idx;
}
return acc;
}
+142
View File
@@ -0,0 +1,142 @@
#ifndef INCLUDED_FIFO_H
#define INCLUDED_FIFO_H
#ifndef INCLUDED_OS_TYPES_H
#include <os_types.h>
#endif /*INCLUDED_OS_TYPES_H*/
#ifndef INCLUDED_OS_COMPILER_H
#include <os_compiler.h>
#endif /*INCLUDED_OS_COMPILER_H*/
#ifndef INCLUDED_OS_MACROS_H
#include <os_macros.h>
#endif /*INCLUDED_OS_MACROS_H*/
/* ==================================================================================================== */
/* 类型 */
typedef struct fifo_t{
uint8_t* buffer;
os_size_t buffer_size;
os_size_t write_idx;
os_size_t read_idx;
}fifo_t;
/* ==================================================================================================== */
/* 接口 */
OS_STATIC_FORCE_INLINE
void fifo_init(fifo_t* self, uint8_t* buffer, os_size_t buffer_size){
OS_ASSERT(self);
OS_ASSERT(buffer);
OS_ASSERT(buffer_size>1);
self->buffer = buffer;
self->buffer_size = buffer_size;
self->write_idx = 0;
self->read_idx = 0;
}
OS_STATIC_FORCE_INLINE
void fifo_clear(fifo_t* self){
self->read_idx = self->write_idx = 0;
}
OS_STATIC_FORCE_INLINE
os_bool_t fifo_is_empty(fifo_t* self){
return (self->write_idx==self->read_idx);
}
// 容量,实际可以存放的字节数
OS_STATIC_FORCE_INLINE
os_size_t fifo_capacity(fifo_t* self){
return self->buffer_size-1;
}
OS_STATIC_FORCE_INLINE
os_bool_t fifo_is_full(fifo_t* self){
os_size_t next_write_idx = self->write_idx + 1;
if(next_write_idx>=self->buffer_size){
next_write_idx = 0;
}
return (next_write_idx==self->read_idx)?OS_TRUE:OS_FALSE;
}
// 数量, 当前buffer里已经有的数据量
OS_STATIC_FORCE_INLINE
os_size_t fifo_count(fifo_t* self){
if(self->write_idx >= self->read_idx){
return (self->write_idx - self->read_idx);
}else{
return (self->buffer_size - self->read_idx) + self->write_idx;
}
}
// 空间, 还可以写入多少字节数据
OS_STATIC_FORCE_INLINE
os_size_t fifo_space(fifo_t* self){
os_size_t count = 0;
if(self->write_idx >= self->read_idx){
count = (self->write_idx - self->read_idx);
}else{
count = (self->buffer_size - self->read_idx) + self->write_idx;
}
return self->buffer_size - 1 - count;
}
OS_STATIC_FORCE_INLINE
os_err_t fifo_skip(fifo_t* self, os_size_t offset){
os_size_t data_sz = fifo_count(self);
if(offset > data_sz){
return OS_ERR_FULL;
}
os_size_t read_idx = self->read_idx;
self->read_idx = (read_idx + offset) % self->buffer_size;
return OS_ERR_OK;
}
OS_STATIC_FORCE_INLINE
os_bool_t fifo_offset_is(fifo_t* self, os_size_t offset, uint8_t data){
OS_ASSERT(offset < fifo_count(self));
os_size_t read_idx = (self->read_idx + offset) % self->buffer_size;
return (data == self->buffer[read_idx])?OS_TRUE:OS_FALSE;
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
// 在尾部写入数据
os_err_t fifo_put(fifo_t* self, uint8_t data);
// 从头部获取数据
os_err_t fifo_get(fifo_t* self, uint8_t* data);
// 批量写入数据
os_size_t fifo_write(fifo_t* self, uint8_t* data, os_size_t size);
// 批量读取数据
os_size_t fifo_read(fifo_t* self, uint8_t* buf, os_size_t size);
os_size_t fifo_write_fast(fifo_t* rb, const uint8_t * data, os_size_t len);
os_size_t fifo_read_fast(fifo_t* rb, uint8_t * data, os_size_t len);
int fifo_memcmp(fifo_t *rb, os_size_t offset, const void *ptr, os_size_t len);
os_size_t fifo_peek_bulk(fifo_t* rb, os_size_t offset, uint8_t* data, os_size_t len);
os_err_t fifo_peek_at(fifo_t* self, os_size_t offset, uint8_t * data);
os_size_t fifo_find(fifo_t *rb, os_size_t offset, const void *pattern, os_size_t pattern_len);
unsigned long fifo_strtoul(fifo_t* self, os_size_t* endptr /*从哪里开始转换, 可以为空*/, int base /*0, 8, 10, 16 进制*/);
#endif /*INCLUDED_FIFO_H*/
+485
View File
@@ -0,0 +1,485 @@
#include <fixed_rbtree.h>
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
#define RED 'R'
#define BLACK 'B'
typedef fixed_rbtree_t rbtree_t;
typedef fixed_rbtree_node_t rbtree_node_t;
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
OS_STATIC_FORCE_INLINE
void node_init(rbtree_t* tree, rbtree_node_t* self, void* key, void* val){
self->left = self->right = self->parent = 0;
self->color = RED;
self->key = key;
self->val = val;
}
OS_STATIC_FORCE_INLINE
void node_destroy(rbtree_t* tree, rbtree_node_t* x){
pool_free(&tree->node_pool, x);
}
OS_STATIC_FORCE_INLINE
void rotate_left(rbtree_t* self, rbtree_node_t* x){
rbtree_node_t * y = x->right;
x->right = y->left;
if(y->left){
y->left->parent = x;
}
y->parent = x->parent;
if(!x->parent){
self->root = y;
} else{
if(x->parent->left==x){
x->parent->left = y;
}else{
x->parent->right = y;
}
}
y->left = x;
x->parent = y;
}
OS_STATIC_FORCE_INLINE
void rotate_right(rbtree_t* self, rbtree_node_t* y){
rbtree_node_t * x = y->left;
y->left = x->right;
if(x->right){
x->right->parent = y;
}
x->parent = y->parent;
if(!y->parent){
self->root = x;
}else{
if(y==y->parent->left){
y->parent->left = x;
}else{
y->parent->right = x;
}
}
x->right = y;
y->parent = x;
}
static fixed_rbtree_node_t* find(rbtree_t* self, const void* key, rbtree_node_t* x){
while(x){
int cmp = self->ops.cmp(key, x->key, self->ops.args);
if(cmp < 0){
x = x->left;
}else if(cmp > 0){
x = x->right;
}else{
return x;
}
}
return NULL;
}
OS_STATIC_FORCE_INLINE
rbtree_node_t * node_parent(rbtree_node_t* x){
return (x!=NULL)?x->parent:NULL;
}
OS_STATIC_FORCE_INLINE
char node_color(rbtree_node_t* x){
return (x!=NULL)?x->color:BLACK;
}
OS_STATIC_FORCE_INLINE
bool node_is_red(rbtree_node_t* x){
return (node_color(x)==RED)?true:false;
}
OS_STATIC_FORCE_INLINE
bool node_is_black(rbtree_node_t* x){
return !node_is_red(x);
}
OS_STATIC_FORCE_INLINE
void node_set_black(rbtree_node_t* x){
if(x){
x->color = BLACK;
}
}
OS_STATIC_FORCE_INLINE
void node_set_red(rbtree_node_t* x){
if(x){
x->color = RED;
}
}
OS_STATIC_FORCE_INLINE
void node_set_color(rbtree_node_t* x, char color){
if(x){
x->color = color;
}
}
OS_STATIC_FORCE_INLINE
void node_set_parent(rbtree_node_t* x, rbtree_node_t* parent){
if(x){
x->parent = parent;
}
}
OS_STATIC_FORCE_INLINE
void node_insert_fixup(rbtree_t * tree, rbtree_node_t* node){
rbtree_node_t * parent=0;
rbtree_node_t * gparent=0;
while(((parent = node->parent)!=NULL) && node_is_red(parent)){
gparent = node_parent(parent);
if(parent==gparent->left){
rbtree_node_t * pUncle = gparent->right;
if((pUncle!=NULL) && node_is_red(pUncle)){
// Case 1条件:叔叔节点是红色
node_set_black(pUncle);
node_set_black(parent);
node_set_red(gparent);
node = gparent;
continue;
}
if(parent->right==node){
// Case 3条件:叔叔是黑色,且当前节点是右孩子
rbtree_node_t * pTmp;
rotate_left(tree, parent);
pTmp = parent;
parent = node;
node = pTmp;
}
// Case 2条件:叔叔是黑色,且当前节点是左孩子。
node_set_black(parent);
node_set_red(gparent);
rotate_right(tree, gparent);
}else{
//若“z的父节点”是“z的祖父节点的右孩子”
rbtree_node_t * pUncle = gparent->left;
if((pUncle!=NULL) && node_is_red(pUncle)) {
// Case 1条件:叔叔节点是红色
node_set_black(pUncle);
node_set_black(parent);
node_set_red(gparent);
node = gparent;
continue;
}
// Case 2条件:叔叔是黑色,且当前节点是左孩子
if(parent->left == node){
rbtree_node_t * pTmp;
rotate_right(tree, parent);
pTmp = parent;
parent = node;
node = pTmp;
}
// Case 3条件:叔叔是黑色,且当前节点是右孩子。
node_set_black(parent);
node_set_red(gparent);
rotate_left(tree, gparent);
}
}
node_set_black(tree->root);
}
OS_STATIC_FORCE_INLINE
void node_insert(rbtree_t* tree, rbtree_node_t* node){
int cmp = 0;
rbtree_node_t * y = NULL;
rbtree_node_t * x = tree->root;
// 1. 将红黑树当作一颗二叉查找树,将节点添加到二叉查找树中。
while (x) {
y = x;
cmp = tree->ops.cmp(node->key, x->key, tree->ops.args);
if (cmp < 0)
x = x->left;
else
x = x->right;
}
// y 是要插入的父节点
node->parent = y;
if(!y){
// 插入根节点
tree->root = node;
}else{
// 判断插入父节点的左边还是右边
cmp = tree->ops.cmp(node->key, y->key, tree->ops.args);
if(cmp < 0){
y->left = node;
}else{
y->right = node;
}
}
// 2. 设置节点的颜色为红色
node->color = RED;
// 3. 将它重新修正为一颗二叉查找树
node_insert_fixup(tree, node);
}
OS_STATIC_FORCE_INLINE
void node_remove_fixeup(rbtree_t* tree, rbtree_node_t* node, rbtree_node_t* parent){
rbtree_node_t * other;
while(parent!=NULL && (node==NULL || node_is_black(node)) && (node!=tree->root) ){
if(parent->left == node){
other= parent->right;
if(node_is_red(other)){
// Case 1: x的兄弟w是红色的
node_set_black(other);
node_set_red(parent);
rotate_left(tree, parent);
other = parent->right;
}
if((other->left==NULL || node_is_black(other->left)) && (other->right==NULL ||
node_is_black(other->right))){
// Case 2: x的兄弟w是黑色,且w的俩个孩子也都是黑色的
node_set_red(other);
node = parent;
parent = node_parent(node);
}else{
if(other->right==NULL || node_is_black(other->right)){
// Case 4: x的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。
node_set_black(other->left);
node_set_red(other);
rotate_right(tree, other);
other = parent->right;
}
// Case 3: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
node_set_color(other, node_color(parent));
node_set_black(parent);
node_set_black(other->right);
rotate_left(tree, parent);
node = tree->root;
break;
}
}else{
other= parent->left;
if(node_is_red(other)){
// Case 1: x的兄弟w是红色的
node_set_black(other);
node_set_red(parent);
rotate_right(tree, parent);
other = parent->left;
}
if((other->left==NULL || node_is_black(other->left)) && (other->right==NULL ||
node_is_black(other->right))){
// Case 2: x的兄弟w是黑色,且w的俩个孩子也都是黑色的
node_set_red(other);
node = parent;
parent = node_parent(node);
}else{
if(other->left==NULL || node_is_black(other->left)){
// Case 4: x的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。
node_set_black(other->right);
node_set_red(other);
rotate_left(tree, other);
other= parent->left;
}
// Case 3: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
node_set_color(other, node_color(parent));
node_set_black(parent);
node_set_black(other->left);
rotate_right(tree, parent);
node = tree->root;
break;
}
}
}
if(node){
node_set_black(node);
}
}
OS_STATIC_FORCE_INLINE
void node_remove(rbtree_t* tree, rbtree_node_t* node){
rbtree_node_t * child=NULL;
rbtree_node_t * parent=NULL;
char color;
// 被删除节点的"左右孩子都不为空"的情况。
if((node->left!=NULL) && (node->right!=NULL)){
// 被删节点的后继节点。(称为"取代节点")
// 用它来取代"被删节点"的位置,然后再将"被删节点"去掉。
rbtree_node_t * replace = node;
// 获取后继节点
replace = replace->right;
while(replace->left){
replace = replace->left;
}
// "node节点"不是根节点(只有根节点不存在父节点)
if(node_parent(node)!=NULL){
if(node->parent->left == node){
node->parent->left = replace;
}else{
node->parent->right = replace;
}
}else{
// "node节点"是根节点,更新根节点。
tree->root = replace;
}
// child是"取代节点"的右孩子,也是需要"调整的节点"。
// "取代节点"肯定不存在左孩子!因为它是一个后继节点。
child = replace->right;
parent= node_parent(replace);
// 保存"取代节点"的颜色
color = node_color(replace);
// "被删除节点"是"它的后继节点的父节点"
if(parent == node){
parent = replace;
}else {
// child 不为空
if(child!=NULL){
node_set_parent(child, parent);
}
parent->left = child;
replace->right = node->right;
node_set_parent(node->right, replace);
}
replace->parent = node->parent;
replace->color = node->color;
replace->left= node->left;
node->left->parent = replace;
if(color==BLACK){
node_remove_fixeup(tree, child, parent);
}
return;
}
if(node->left!=NULL){
child = node->left;
}else{
child= node->right;
}
parent = node->parent;
color = node->color;
if(child!=NULL){
child->parent = parent;
}
// "node节点"不是根节点
if(parent){
if(parent->left==node){
parent->left = child;
}else{
parent->right = child;
}
}else{
tree->root = child;
}
if(color==BLACK){
node_remove_fixeup(tree, child, parent);
}
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
void fixed_rbtree_init(fixed_rbtree_t* self, void* node_block, os_size_t node_block_size, fixed_rbtree_ops_t ops){
pool_init(&self->node_pool, sizeof(fixed_rbtree_node_t));
pool_add_block(&self->node_pool, node_block, node_block_size);
self->ops = ops;
self->root = 0;
}
void fixed_rbtree_add_node_pool(fixed_rbtree_t* self, void* node_block, os_size_t node_block_size){
pool_add_block(&self->node_pool, node_block, node_block_size);
}
void fixed_rbtree_destroy(fixed_rbtree_t* self){
while(self->root){
fixed_rbtree_node_t* p = self->root;
node_remove(self, self->root);
node_destroy(self, p);
}
}
fixed_rbtree_node_t* fixed_rbtree_find(fixed_rbtree_t* self, const void* key){
if(key==NULL) return NULL;
return find(self, key, self->root);
}
fixed_rbtree_node_t* fixed_rbtree_custom_find(fixed_rbtree_t* self, const void* key
, fixed_rbtree_node_t* (*custom_find)(fixed_rbtree_t* tree, const void* key, fixed_rbtree_node_t* x, void* args)
, void* args)
{
if(key==NULL) return NULL;
return custom_find(self, key, self->root, args);
}
os_err_t fixed_rbtree_insert(fixed_rbtree_t* self, void* key, void* val){
fixed_rbtree_node_t* p = pool_alloc(&self->node_pool);
if(!p){
return OS_ERR_FAIL;
}
node_init(self, p, key, val);
node_insert(self, p);
return OS_ERR_OK;
}
void fixed_rbtree_remove(fixed_rbtree_t* self, const void* key){
fixed_rbtree_node_t * pNode = fixed_rbtree_find(self, key);
if(pNode==NULL){
return;
}
node_remove(self, pNode);
node_destroy(self, pNode);
}
void fixed_rbtree_remove_node(fixed_rbtree_t* self, fixed_rbtree_node_t* x){
if(x==NULL) return;
node_remove(self, x);
node_destroy(self, x);
}
static void in_order(fixed_rbtree_t* self, fixed_rbtree_node_t* x,
int (*apply)(fixed_rbtree_t* tree, fixed_rbtree_node_t* x, void* args), void* args){
if(x){
in_order(self, x->left, apply, args);
if(apply(self, x, args)==0){
return;
}
in_order(self, x->right, apply, args);
}
}
void fixed_rbtree_inorder(fixed_rbtree_t* self
, int (*apply)(fixed_rbtree_t* tree, fixed_rbtree_node_t* x, void* args), void* args){
in_order(self, self->root, apply, args);
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
+53
View File
@@ -0,0 +1,53 @@
#ifndef INCLUDED_FIXED_RBTREE_H
#define INCLUDED_FIXED_RBTREE_H
#ifndef INCLUDED_OS_TYPES_H
#include <os_types.h>
#endif /*INCLUDED_OS_TYPES_H*/
#ifndef INCLUDED_POOL_H
#include <pool.h>
#endif /*INCLUDED_POOL_H*/
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
typedef struct fixed_rbtree_node_s{
struct fixed_rbtree_node_s* left;
struct fixed_rbtree_node_s* right;
struct fixed_rbtree_node_s* parent;
char color;
void* key;
void* val;
}fixed_rbtree_node_t;
typedef struct {
int (*cmp)(const void* key_a, const void* key_b, void* args);
void* args;
}fixed_rbtree_ops_t;
typedef struct {
fixed_rbtree_node_t* root;
fixed_rbtree_ops_t ops;
pool_t node_pool;
}fixed_rbtree_t;
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
// 初始化时指定一个 node 的对象池,最大只能容纳这些 node
void fixed_rbtree_init(fixed_rbtree_t* self, void* node_block, os_size_t node_block_size, fixed_rbtree_ops_t ops);
void fixed_rbtree_add_node_pool(fixed_rbtree_t* self, void* node_block, os_size_t node_block_size);
void fixed_rbtree_destroy(fixed_rbtree_t* self);
fixed_rbtree_node_t* fixed_rbtree_find(fixed_rbtree_t* self, const void* key);
fixed_rbtree_node_t* fixed_rbtree_custom_find(fixed_rbtree_t* self, const void* key
, fixed_rbtree_node_t* (*custom_find)(fixed_rbtree_t* tree, const void* key, fixed_rbtree_node_t* x, void* args)
, void* args);
os_err_t fixed_rbtree_insert(fixed_rbtree_t* self, void* key, void* val);
void fixed_rbtree_remove(fixed_rbtree_t* self, const void* key);
void fixed_rbtree_remove_node(fixed_rbtree_t* self, fixed_rbtree_node_t* x);
void fixed_rbtree_inorder(fixed_rbtree_t* self
, int (*apply)(fixed_rbtree_t* tree, fixed_rbtree_node_t* x, void* args), void* args);
#endif /*INCLUDED_FIXED_RBTREE_H*/
+471
View File
@@ -0,0 +1,471 @@
#include <fixed_rbtree_pool.h>
#include "os_macros.h"
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
typedef fixed_rbtree_pool_t rbtree_t;
typedef fixed_rbtree_pool_node_t rbtree_node_t;
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
#define RED 'R'
#define BLACK 'B'
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
OS_STATIC_FORCE_INLINE
void node_init(rbtree_t* tree, rbtree_node_t* self, os_size_t obj_size, void* block, os_size_t block_size){
self->left = self->right = self->parent = 0;
self->color = RED;
pool_init(&self->pool, obj_size);
pool_add_block(&self->pool, block, block_size);
}
static
int node_cmp(const os_size_t obj_size, const rbtree_node_t* x, void* args){
return (obj_size == x->pool.obj_size)?0:((obj_size > x->pool.obj_size)?1:-1);
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
OS_STATIC_FORCE_INLINE
void node_destroy(rbtree_t* tree, rbtree_node_t* x){
pool_free(&tree->node_pool, x);
}
OS_STATIC_FORCE_INLINE
void rotate_left(rbtree_t* self, rbtree_node_t* x){
rbtree_node_t * y = x->right;
x->right = y->left;
if(y->left){
y->left->parent = x;
}
y->parent = x->parent;
if(!x->parent){
self->root = y;
} else{
if(x->parent->left==x){
x->parent->left = y;
}else{
x->parent->right = y;
}
}
y->left = x;
x->parent = y;
}
OS_STATIC_FORCE_INLINE
void rotate_right(rbtree_t* self, rbtree_node_t* y){
rbtree_node_t * x = y->left;
y->left = x->right;
if(x->right){
x->right->parent = y;
}
x->parent = y->parent;
if(!y->parent){
self->root = x;
}else{
if(y==y->parent->left){
y->parent->left = x;
}else{
y->parent->right = x;
}
}
x->right = y;
y->parent = x;
}
static rbtree_node_t* find(rbtree_t* self, const os_size_t obj_size, rbtree_node_t* x){
while(x){
int cmp = node_cmp(obj_size, x, 0);
if(cmp < 0){
x = x->left;
}else if(cmp > 0){
x = x->right;
}else{
return x;
}
}
return NULL;
}
OS_STATIC_FORCE_INLINE
rbtree_node_t * node_parent(rbtree_node_t* x){
return (x!=NULL)?x->parent:NULL;
}
OS_STATIC_FORCE_INLINE
char node_color(rbtree_node_t* x){
return (x!=NULL)?x->color:BLACK;
}
OS_STATIC_FORCE_INLINE
bool node_is_red(rbtree_node_t* x){
return (node_color(x)==RED)?true:false;
}
OS_STATIC_FORCE_INLINE
bool node_is_black(rbtree_node_t* x){
return !node_is_red(x);
}
OS_STATIC_FORCE_INLINE
void node_set_black(rbtree_node_t* x){
if(x){
x->color = BLACK;
}
}
OS_STATIC_FORCE_INLINE
void node_set_red(rbtree_node_t* x){
if(x){
x->color = RED;
}
}
OS_STATIC_FORCE_INLINE
void node_set_color(rbtree_node_t* x, char color){
if(x){
x->color = color;
}
}
OS_STATIC_FORCE_INLINE
void node_set_parent(rbtree_node_t* x, rbtree_node_t* parent){
if(x){
x->parent = parent;
}
}
OS_STATIC_FORCE_INLINE
void node_insert_fixup(rbtree_t* tree, rbtree_node_t* node){
rbtree_node_t * parent=0;
rbtree_node_t * gparent=0;
while(((parent = node->parent)!=NULL) && node_is_red(parent)){
gparent = node_parent(parent);
if(parent==gparent->left){
rbtree_node_t * pUncle = gparent->right;
if((pUncle!=NULL) && node_is_red(pUncle)){
// Case 1条件:叔叔节点是红色
node_set_black(pUncle);
node_set_black(parent);
node_set_red(gparent);
node = gparent;
continue;
}
if(parent->right==node){
// Case 3条件:叔叔是黑色,且当前节点是右孩子
rbtree_node_t * pTmp;
rotate_left(tree, parent);
pTmp = parent;
parent = node;
node = pTmp;
}
// Case 2条件:叔叔是黑色,且当前节点是左孩子。
node_set_black(parent);
node_set_red(gparent);
rotate_right(tree, gparent);
}else{
//若“z的父节点”是“z的祖父节点的右孩子”
rbtree_node_t * pUncle = gparent->left;
if((pUncle!=NULL) && node_is_red(pUncle)) {
// Case 1条件:叔叔节点是红色
node_set_black(pUncle);
node_set_black(parent);
node_set_red(gparent);
node = gparent;
continue;
}
// Case 2条件:叔叔是黑色,且当前节点是左孩子
if(parent->left == node){
rbtree_node_t * pTmp;
rotate_right(tree, parent);
pTmp = parent;
parent = node;
node = pTmp;
}
// Case 3条件:叔叔是黑色,且当前节点是右孩子。
node_set_black(parent);
node_set_red(gparent);
rotate_left(tree, gparent);
}
}
node_set_black(tree->root);
}
OS_STATIC_FORCE_INLINE
void node_insert(rbtree_t* tree, rbtree_node_t* node){
int cmp = 0;
rbtree_node_t * y = NULL;
rbtree_node_t * x = tree->root;
// 1. 将红黑树当作一颗二叉查找树,将节点添加到二叉查找树中。
while (x) {
y = x;
cmp = node_cmp(node->pool.obj_size, x,0);
if (cmp < 0)
x = x->left;
else
x = x->right;
}
// y 是要插入的父节点
node->parent = y;
if(!y){
// 插入根节点
tree->root = node;
}else{
// 判断插入父节点的左边还是右边
cmp = node_cmp(node->pool.obj_size, y, 0);
if(cmp < 0){
y->left = node;
}else{
y->right = node;
}
}
// 2. 设置节点的颜色为红色
node->color = RED;
// 3. 将它重新修正为一颗二叉查找树
node_insert_fixup(tree, node);
}
OS_STATIC_FORCE_INLINE
void node_remove_fixeup(rbtree_t* tree, rbtree_node_t* node, rbtree_node_t* parent){
rbtree_node_t * other;
while(parent!=NULL && (node==NULL || node_is_black(node)) && (node!=tree->root) ){
if(parent->left == node){
other= parent->right;
if(node_is_red(other)){
// Case 1: x的兄弟w是红色的
node_set_black(other);
node_set_red(parent);
rotate_left(tree, parent);
other = parent->right;
}
if((other->left==NULL || node_is_black(other->left)) && (other->right==NULL ||
node_is_black(other->right))){
// Case 2: x的兄弟w是黑色,且w的俩个孩子也都是黑色的
node_set_red(other);
node = parent;
parent = node_parent(node);
}else{
if(other->right==NULL || node_is_black(other->right)){
// Case 4: x的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。
node_set_black(other->left);
node_set_red(other);
rotate_right(tree, other);
other = parent->right;
}
// Case 3: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
node_set_color(other, node_color(parent));
node_set_black(parent);
node_set_black(other->right);
rotate_left(tree, parent);
node = tree->root;
break;
}
}else{
other= parent->left;
if(node_is_red(other)){
// Case 1: x的兄弟w是红色的
node_set_black(other);
node_set_red(parent);
rotate_right(tree, parent);
other = parent->left;
}
if((other->left==NULL || node_is_black(other->left)) && (other->right==NULL ||
node_is_black(other->right))){
// Case 2: x的兄弟w是黑色,且w的俩个孩子也都是黑色的
node_set_red(other);
node = parent;
parent = node_parent(node);
}else{
if(other->left==NULL || node_is_black(other->left)){
// Case 4: x的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。
node_set_black(other->right);
node_set_red(other);
rotate_left(tree, other);
other= parent->left;
}
// Case 3: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
node_set_color(other, node_color(parent));
node_set_black(parent);
node_set_black(other->left);
rotate_right(tree, parent);
node = tree->root;
break;
}
}
}
if(node){
node_set_black(node);
}
}
OS_STATIC_FORCE_INLINE
void node_remove(rbtree_t* tree, rbtree_node_t* node){
rbtree_node_t * child=NULL;
rbtree_node_t * parent=NULL;
char color;
// 被删除节点的"左右孩子都不为空"的情况。
if((node->left!=NULL) && (node->right!=NULL)){
// 被删节点的后继节点。(称为"取代节点")
// 用它来取代"被删节点"的位置,然后再将"被删节点"去掉。
rbtree_node_t * replace = node;
// 获取后继节点
replace = replace->right;
while(replace->left){
replace = replace->left;
}
// "node节点"不是根节点(只有根节点不存在父节点)
if(node_parent(node)!=NULL){
if(node->parent->left == node){
node->parent->left = replace;
}else{
node->parent->right = replace;
}
}else{
// "node节点"是根节点,更新根节点。
tree->root = replace;
}
// child是"取代节点"的右孩子,也是需要"调整的节点"。
// "取代节点"肯定不存在左孩子!因为它是一个后继节点。
child = replace->right;
parent= node_parent(replace);
// 保存"取代节点"的颜色
color = node_color(replace);
// "被删除节点"是"它的后继节点的父节点"
if(parent == node){
parent = replace;
}else {
// child 不为空
if(child!=NULL){
node_set_parent(child, parent);
}
parent->left = child;
replace->right = node->right;
node_set_parent(node->right, replace);
}
replace->parent = node->parent;
replace->color = node->color;
replace->left= node->left;
node->left->parent = replace;
if(color==BLACK){
node_remove_fixeup(tree, child, parent);
}
return;
}
if(node->left!=NULL){
child = node->left;
}else{
child= node->right;
}
parent = node->parent;
color = node->color;
if(child!=NULL){
child->parent = parent;
}
// "node节点"不是根节点
if(parent){
if(parent->left==node){
parent->left = child;
}else{
parent->right = child;
}
}else{
tree->root = child;
}
if(color==BLACK){
node_remove_fixeup(tree, child, parent);
}
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
void fixed_rbtree_pool_init(fixed_rbtree_pool_t* self, void* node_block, os_size_t node_block_size){
self->root = 0;
pool_init(&self->node_pool, sizeof(fixed_rbtree_pool_node_t));
pool_add_block(&self->node_pool, node_block, node_block_size);
}
void fixed_rbtree_pool_add_node_pool(fixed_rbtree_pool_t* self, void* node_block, os_size_t node_block_size){
pool_add_block(&self->node_pool, node_block, node_block_size);
}
void fixed_rbtree_pool_destroy(fixed_rbtree_pool_t* self){
while(self->root){
rbtree_node_t * p = self->root;
node_remove(self, p);
node_destroy(self, p);
}
}
void fixed_rbtree_pool_add(fixed_rbtree_pool_t* self, os_size_t obj_size, void* block, os_size_t block_size){
rbtree_node_t* x = find(self, obj_size, self->root);
if(x==NULL){
x = pool_alloc(&self->node_pool);
node_init(self, x, obj_size, block, block_size);
node_insert(self, x);
}else{
pool_add_block(&x->pool, block, block_size);
}
}
void* fixed_rbtree_pool_alloc(fixed_rbtree_pool_t* self, os_size_t obj_size){
rbtree_node_t * x = find(self, obj_size, self->root);
OS_ASSERT(x, "No pool exist for obj_size: %"OS_PRIu, obj_size);
if(x==NULL){
return NULL;
}
return pool_alloc(&x->pool);
}
void fixed_rbtree_pool_free(fixed_rbtree_pool_t* self, os_size_t obj_size, void* ptr){
if(!ptr) return;
rbtree_node_t * x = find(self, obj_size, self->root);
OS_ASSERT(x, "No pool exist for obj_size: %"OS_PRIu, obj_size);
if(x==NULL){
return;
}
pool_free(&self->node_pool, ptr);
}
+43
View File
@@ -0,0 +1,43 @@
#ifndef INCLUDED_FIXED_RBTREE_POOL_H
#define INCLUDED_FIXED_RBTREE_POOL_H
#ifndef INCLUDED_OS_TYPES_H
#include <os_types.h>
#endif /*INCLUDED_OS_TYPES_H*/
#ifndef INCLUDED_POOL_H
#include <pool.h>
#endif /*INCLUDED_POOL_H*/
/* ------------------------------------------------------------------------------------------------------------------ */
/*
* 1. 只能支持固定数量的 node 节点
* 2. 根据 obj_size 建立不同的对象池,同样大小的对象都通过同一个池进行分配
*/
typedef struct fixed_rbtree_pool_block_s{
struct fixed_rbtree_pool_block_s* left;
struct fixed_rbtree_pool_block_s* right;
struct fixed_rbtree_pool_block_s* parent;
char color;
pool_t pool;
}fixed_rbtree_pool_node_t;
typedef struct {
fixed_rbtree_pool_node_t* root;
pool_t node_pool;
}fixed_rbtree_pool_t;
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
void fixed_rbtree_pool_init(fixed_rbtree_pool_t* self, void* node_block, os_size_t node_block_size);
void fixed_rbtree_pool_add_node_pool(fixed_rbtree_pool_t* self, void* node_block, os_size_t node_block_size);
void fixed_rbtree_pool_destroy(fixed_rbtree_pool_t* self);
void fixed_rbtree_pool_add(fixed_rbtree_pool_t* self, os_size_t obj_size, void* block, os_size_t block_size);
void* fixed_rbtree_pool_alloc(fixed_rbtree_pool_t* self, os_size_t obj_size);
void fixed_rbtree_pool_free(fixed_rbtree_pool_t* self, os_size_t obj_size, void* ptr);
#endif /*INCLUDED_FIXED_RBTREE_POOL_H*/
+68
View File
@@ -0,0 +1,68 @@
#include <ieee_float.h>
#include <math.h>
#include <stdlib.h>
int ieee_float_cmp(const float a, const float b, const float maxDiff){
float diff = a-b;
if(fabsf(diff) <= maxDiff){
return 0;
}else{
return (diff > maxDiff)?1:-1;
}
}
int ieee_double_cmp(const double a, const double b, const double maxDiff){
double diff = a-b;
if(fabs(diff) <= maxDiff){
return 0;
}else{
return (diff > maxDiff)?1:-1;
}
}
int ieee_float_UlpsCmp(const float a, const float b, const float maxFloatDiff, const int maxUlpsDiff){
const float absDiff = fabsf(a-b);
if(absDiff <= maxFloatDiff){
return 0;
}
ieee_float_t A;
ieee_float_t B;
A.value.f = a;
B.value.f = b;
if(A.value.IEEE754.sign != B.value.IEEE754.sign){
return (int)(B.value.IEEE754.sign - A.value.IEEE754.sign);
}
const int ulpsDiff = abs((int)(A.value.uint - B.value.uint));
if(ulpsDiff <= maxUlpsDiff){
return 0;
}
return (ulpsDiff > maxUlpsDiff)?1:-1;
}
int ieee_double_UlpsCmp(const double a, const double b, const double maxFloatDiff, const int maxUlpsDiff){
const double absDiff = fabs(a-b);
if(absDiff <= maxFloatDiff){
return 0;
}
ieee_double_t A = {.value.f = a};
ieee_double_t B = {.value.f = b};
if(A.value.IEEE754.sign != B.value.IEEE754.sign){
return (int)(B.value.IEEE754.sign - A.value.IEEE754.sign);
}
const int ulpsDiff = abs((int)(A.value.uint - B.value.uint));
if(ulpsDiff <= maxUlpsDiff){
return 0;
}
return (ulpsDiff > maxUlpsDiff)?1:-1;
}
bool ieee_float_is_zero(const float a, const float maxDiff){
return (fabsf(a) <= maxDiff)?true:false;
}
bool ieee_double_is_zero(const double a, const double maxDiff){
return (fabs(a) <= maxDiff)?true:false;
}
+72
View File
@@ -0,0 +1,72 @@
#ifndef INCLUDED_IEEE_FLOAT_H
#define INCLUDED_IEEE_FLOAT_H
#ifndef INCLUDED_STDINT_H
#define INCLUDED_STDINT_H
#include <stdint.h>
#endif /*INCLUDED_STDINT_H*/
#ifndef INCLUDED_FLOAT_H
#define INCLUDED_FLOAT_H
#include <float.h>
#endif /*INCLUDED_FLOAT_H*/
#ifndef INCLUDED_STDBOOL_H
#define INCLUDED_STDBOOL_H
#include <stdbool.h>
#endif /*INCLUDED_STDBOOL_H*/
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
typedef struct {
union{
struct{
uint32_t sign:1;
uint32_t exponent:8;
uint32_t mantissa:23;
}IEEE754;
uint32_t uint;
float f;
}value;
}ieee_float_t;
typedef struct {
union{
struct{
uint64_t sign:1;
uint64_t exponent:11;
uint64_t mantissa:52;
}IEEE754;
uint64_t uint;
double f;
}value;
}ieee_double_t;
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
#define IEEE_FLOAT_POSITIVE_INFINITY (1.0f/0.0f)
#define IEEE_FLOAT_NEGATIVE_INFINITY (-1.0f/0.0f)
#define IEEE_FLOAT_NAN (0.0f/0.0f)
#define IEEE_FLOAT_EPSILON (FLT_EPSILON)
#define IEEE_DOUBLE_EPSILON (DBL_EPSILON)
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
int ieee_float_cmp(const float a, const float b, const float maxDiff);
int ieee_double_cmp(const double a, const double b, const double maxDiff);
// 当将 float 看作 uint32 时进行比较,maxUlpsDiff 就是作为无符号整数允许的最大差异,一般取 `1` 就可以
// maxFloatDiff 一般取 IEEE_FLOAT_EPSILON, 是将数值作为 float 进行比较,但是如果两个 float 无法完成比较,就可以通过
// 无符号整数的形式来进行比较
int ieee_float_UlpsCmp(const float a, const float b, const float maxFloatDiff, const int maxUlpsDiff);
int ieee_double_UlpsCmp(const double a, const double b, const double maxFloatDiff, const int maxUlpsDiff);
bool ieee_float_is_zero(const float a, const float maxDiff);
bool ieee_double_is_zero(const double a, const double maxDiff);
#endif /*INCLUDED_IEEE_FLOAT_H*/
+23
View File
@@ -0,0 +1,23 @@
#include <pool.h>
#include "os_macros.h"
#include "os_align.h"
void pool_add_block(pool_t* self, void* block, os_size_t block_size){
// 对齐
os_uintptr_t init_start = (os_uintptr_t)block; // 初始的位置
os_uintptr_t start = OS_ALIGN_UP(init_start, OS_ALIGN_SIZE); // 向上对齐后的位置
block_size -= (start - init_start); // 实际使用的块大小
OS_ASSERT(block_size > self->obj_size);
// 将内存块拆成 obj_size 大小
os_size_t count = block_size/self->obj_size;
uint8_t * last = &(((uint8_t*)start)[(count - 1) * self->obj_size]);
for(uint8_t * p = (uint8_t*)start; p<last; p+=self->obj_size){
((pool_link_t*)p)->next = (pool_link_t*)(p+self->obj_size);
}
((pool_link_t*)last)->next = 0;
self->free_list_p = (pool_link_t*)start;
self->capacity += count;
}
+80
View File
@@ -0,0 +1,80 @@
#ifndef INCLUDED_POOL_H
#define INCLUDED_POOL_H
#ifndef INCLUDED_OS_TYPES_H
#include <os_types.h>
#endif /*INCLUDED_OS_TYPES_H*/
#ifndef INCLUDED_OS_COMPILER_H
#include <os_compiler.h>
#endif /*INCLUDED_OS_COMPILER_H*/
/* ------------------------------------------------------------------------------------------------------------------ */
/* https://www.gingerbill.org/article/2019/02/16/memory-allocation-strategies-004/ */
typedef struct pool_link_s {
struct pool_link_s* next;
}pool_link_t;
typedef struct {
pool_link_t* free_list_p; /* 对象内存链表,每个节点指向一个对象内存地址 */
os_size_t obj_size; /* 每个对象的大小 */
os_size_t capacity; /* 池中最大能分配的对象数量 */
os_size_t count; /* 已分配的对象数量 */
}pool_t;
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
void pool_add_block(pool_t* self, void* block, os_size_t block_size);
/*
* pool_t pool;
* uint8_t block1[512];
* uint8_t block2[1024];
* uint8_t block3[256];
*
* pool_init(&pool, 16);
* pool_add_block(&pool, block1, 512);
* pool_add_block(&pool, block2, 1024);
* pool_add_block(&pool, block3, 256);
*
* void* obj1 = pool_alloc(&pool);
* ...
* pool_free(&pool, obj1);
*
*/
OS_STATIC_FORCE_INLINE
void pool_init(pool_t* self, os_size_t obj_size){
self->free_list_p = 0;
self->obj_size = obj_size;
self->count = 0;
self->capacity = 0;
}
OS_STATIC_FORCE_INLINE
void* pool_alloc(pool_t* self){
if(!self->free_list_p){
return NULL;
}
pool_link_t* p = self->free_list_p;
self->free_list_p = p->next;
self->count++;
return p;
}
OS_STATIC_FORCE_INLINE
void pool_free(pool_t* self, void* obj){
pool_link_t* p_link = (pool_link_t*) obj;
p_link->next = self->free_list_p;
self->free_list_p = p_link;
self->count--;
}
#endif /*INCLUDED_POOL_H*/