util: add fixed-size stack

This commit is contained in:
Edgaru089 2021-10-23 20:57:29 +08:00
parent 55d3da43a2
commit 6bd5e2dbab
2 changed files with 123 additions and 0 deletions

71
util/stack.c Normal file
View File

@ -0,0 +1,71 @@
#include "stack.h"
#include "../runtime/stdio.h"
#include <memory.h>
void stack_InitBuffered(stack *s, void *buffer, uintptr_t size) {
s->data = buffer;
s->size = size;
s->top = buffer + size;
}
void stack_PushByte(stack *s, const uint8_t b) {
if (s->top <= s->data) {
io_Printf("stack_PushByte: full[%llu bytes], discarding byte 0x%x\n", s->size, b);
return;
}
*(uint8_t *)--s->top = b;
}
uint8_t stack_PopByte(stack *s) {
if (s->top == s->data + s->size) {
io_WriteConsoleASCII("stack_PopByte: popping an empty stack\n");
return 0;
}
return *(uint8_t *)s->top++;
}
void stack_Push(stack *s, const void *buffer, uintptr_t size) {
if (stack_Space(s) < size) {
io_Printf("stack_Push: insufficient space (%d/%d bytes, want %d bytes)\n", stack_Size(s), s->size, size);
return;
}
s->top -= size;
memcpy(s->top, buffer, size);
}
uintptr_t stack_Pop(stack *s, void *buffer, uintptr_t size) {
if (stack_Size(s) < size)
return 0;
memcpy(buffer, s->top, size);
s->top += size;
return size;
}
uint8_t stack_TopByte(stack *s) {
if (stack_Empty(s)) {
io_WriteConsoleASCII("stack_TopByte: called on an empty stack\n");
return 0;
}
return *(uint8_t *)s->top;
}
uintptr_t stack_Top(stack *s, void *buffer, uintptr_t size) {
if (stack_Size(s) < size)
return 0;
memcpy(buffer, s->top, size);
return size;
}
bool stack_Empty(stack *s) {
return s->top == s->data + s->size;
}
uintptr_t stack_Size(stack *s) {
return s->data + s->size - s->top;
}
uintptr_t stack_Space(stack *s) {
return s->top - s->data;
}

52
util/stack.h Normal file
View File

@ -0,0 +1,52 @@
#pragma once
#include "../main.h"
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
void * data; // the data buffer
uintptr_t size; // size of data buffer
void * top; // top of the stack, the stack grows downward (from data+size to data)
} stack;
// initialize a stack with a existing buffer
void stack_InitBuffered(stack *s, void *buffer, uintptr_t size);
// pushes one byte to the stack, discarding if full
void stack_PushByte(stack *s, const uint8_t b);
// pops one byte from the top of the stack, returning it
uint8_t stack_PopByte(stack *s);
// pushes Size bytes to the stack, none written if there is not space for all the bytes
void stack_Push(stack *s, const void *buffer, uintptr_t size);
// pops Size bytes from the stack, none popped if there are no enough data
// returns the number of bytes popped (either Size or 0)
uintptr_t stack_Pop(stack *s, void *buffer, uintptr_t size);
// return the byte at the top of the stack
uint8_t stack_TopByte(stack *s);
// copy the bytes at the top of the stack
// returns the number of bytes copied
uintptr_t stack_Top(stack *s, void *buffer, uintptr_t size);
// tells if the stack is empty
bool stack_Empty(stack *s);
// returns the number of bytes in the stack
uintptr_t stack_Size(stack *s);
// returns the empty space left in the stack
uintptr_t stack_Space(stack *s);
#ifdef __cplusplus
}
#endif